Array.prototype.unshift方法详解
前言⁍
最近看到这么一道面试题
输出以下代码执行的结果并解释为什么[1]
1 |
|
试了一下,结果如下:
1 |
|
这是因为push
方法根据 length
属性来决定从哪里开始插入给定的值。[2]
之后好奇试了一下pop
和shift
方法,pop
属性也是根据length
属性来决定位置,而shift
属性总是从第一个位置开始移除元素。所以这两个方法的结果都是只有length
减少,直至0,就不变了。
问题⁍
问题就出在unshift
方法上。
1 |
|
当我们移入0
时,位于下标2的3
被删除了,而位于下标3的4
却没变。感觉和想象的不太一样。
分析⁍
对于这个方法,mdn上的描述是:[3]
unshift()
方法将一个或多个元素添加到数组的开头,并返回该数组的新长度。
看上去没什么,不过mdn还给出了它的ECMAScript规范[4]其中是这么写的
- 1. Let O be ? ToObject(this value).
- 2. Let len be ? LengthOfArrayLike(O).
- 3. Let argCount be the number of elements in items.
- 4. If argCount > 0, then
- a. If len + argCount > 253 - 1, throw a TypeError exception.
- b. Let k be len.
- c. Repeat, while k > 0,
- i. Let from be ! ToString(𝔽(k - 1)).
- ii. Let to be ! ToString(𝔽(k + argCount - 1)).
- iii. Let fromPresent be ? HasProperty(O, from).
- iv. If fromPresent is true, then
- v. Else,
- 1. Assert: fromPresent is false.
- 2. Perform ? DeletePropertyOrThrow(O, to).
- vi. Set k to k - 1.
- d. Let j be +0𝔽.
- e. For each element E of items, do
- 5. Perform ? Set(O, “length”, 𝔽(len + argCount), true).
- 6. Return 𝔽(len + argCount).
虽然没有完全看懂,但翻译成人话,大概是这么个流程
对于原题中的数组来说,一开始from
是1,此时数组中不存在下标为1的值,所以要把to
也就是2-1+1=2下标处的值(即'2':3
)删除掉;k-1
后为1
,from
变为0
,也不存在,k
继续减至0。从0开始移入新加入的值,结果就是
{'0':0,'3':4}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 若叶!