search

Home  >  Q&A  >  body text

javascript - 一道阿里巴巴实习笔试题引发的问题


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

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

巴扎黑巴扎黑2817 days ago328

reply all(5)I'll reply

  • PHP中文网

    PHP中文网2017-04-10 15:06:05

    不知道楼主是不是看了我的贴发现了这道题。抱歉啊,最开始从图到文字的时候,敲错了,没把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 方法调用时候的步骤。可以研究一下。

    reply
    0
  • 怪我咯

    怪我咯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所表示的位置插入或覆盖当前值。

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 15:06:05

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

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

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 15:06:05

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

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 15:06:05

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

    reply
    0
  • Cancelreply