javascript - 一道阿里巴巴实习笔试题引发的问题
巴扎黑
巴扎黑 2017-04-10 15:04:05
0
5
335


如图,很容易可以看出Array的push方法的机制就是如果对象中有length属性,那么就根据length属性在对象中插入,但是插入之后其他值的变化无法理解,比如怎么就出现了'bb'和2,大家一起讨论下

非常抱歉,我是在Chrome开发者工具中测试的,可能当时页面中有a和b两个变量,所以没去注意这个问题,非常抱歉,a,b按照字符来看待就没问题了

巴扎黑
巴扎黑

reply all(5)
洪涛

不知道楼主是不是看了我的贴发现了这道题。抱歉啊,最开始从图到文字的时候,敲错了,没把a,b加上引号。。它俩确实是个字符串。所以原题应该是:

javascriptvar obj = {
    '1':'a',
    '2':'b',
    'length':2,
    push:Array.prototype.push
}
obj.push('c');

下面说一下Array.prototype.push。
js Array 的源码好像是这个
V8
Array.prototype.push的部分貌似是这个:

javascriptfunction 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;
}

另外还有一些规范性的说明:

  • MDN

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'。

  • ECMAScript 5
    里面详细介绍了 push 方法调用时候的步骤。可以研究一下。
刘奇

你这个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所表示的位置插入或覆盖当前值。

巴扎黑

你这样问问题会误导别人的,你的a和b如果不是变量的话,你上面的语句是根本没有办法执行的。

同意楼上的意见,你自己再仔细看看题目是不是完全

伊谢尔伦

这个题是javascript中伪数组的问题,建议你查看大犀牛中的解释

Ty80

http://yanhaijing.com/es5/#349

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template