如图,很容易可以看出Array的push方法的机制就是如果对象中有length属性,那么就根据length属性在对象中插入,但是插入之后其他值的变化无法理解,比如怎么就出现了'bb'和2,大家一起讨论下
非常抱歉,我是在Chrome开发者工具中测试的,可能当时页面中有a和b两个变量,所以没去注意这个问题,非常抱歉,a,b按照字符来看待就没问题了
PHP中文网2017-04-10 15:06:05
不知道楼主是不是看了我的贴发现了这道题。抱歉啊,最开始从图到文字的时候,敲错了,没把a,b加上引号。。它俩确实是个字符串。所以原题应该是:
javascript
var obj = { '1':'a', '2':'b', 'length':2, push:Array.prototype.push } obj.push('c');
下面说一下Array.prototype.push。
js Array 的源码好像是这个
V8
Array.prototype.push的部分貌似是这个:
javascript
function ObservedArrayPush() { var n = TO_UINT32(this.length); var m = %_ArgumentsLength(); try { BeginPerformSplice(this); for (var i = 0; i < m; i++) { this[i+n] = %_Arguments(i); } var new_length = n + m; this.length = new_length; } finally { EndPerformSplice(this); EnqueueSpliceRecord(this, n, [], m); } return new_length; } // Appends the arguments to the end of the array and returns the new // length of the array. See ECMA-262, section 15.4.4.7. function ArrayPush() { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push"); if (%IsObserved(this)) return ObservedArrayPush.apply(this, arguments); var array = TO_OBJECT_INLINE(this); var n = TO_UINT32(array.length); var m = %_ArgumentsLength(); for (var i = 0; i < m; i++) { array[i+n] = %_Arguments(i); } var new_length = n + m; array.length = new_length; return new_length; }
另外还有一些规范性的说明:
push 方法把值添加到数组中。
push 方法有意具有通用性。该方法和 call() 或 apply() 一起使用时,可应用在类似数组的对象上。push 方法根据 length 属性来决定从哪里开始插入给定的值。如果 length 不能被转成一个数值,则插入的元素索引为 0,包括 length 不存在时。当 length 不存在时,将会创建它。
唯一的原生类数组(array-like)对象是 Strings,尽管如此,它们并不适用该方法,因为字符串是不可改变的。
所以说,push会根据对象length属性的值去确定插入的位置,即类似于this[this.length]=arguments[i]
。
所以在原题中obj.length
值为2,调用obj.push("c")
时,会发生obj[2]="c"的情况,所以最后 obj[2]就变成了'c',而不是原来的'b'。
怪我咯2017-04-10 15:06:05
你这个a和b不是变量么?a的值是2,b的值是'bb'。
在网上找到一个push方法的实现,不知道正确与否,试了一下结果跟你一样的。
Array.prototype.push=function(){
var len=arguments.length;
if(len>0)for(var i=0;i<len;i++)this[this.length]=arguments[i];
return this.length;
}
是在当前length所表示的位置插入或覆盖当前值。