为什么我的类数组对象的长度属性会改变?

3

我正在学习JavaScript的callapply方法,但在例子中使用的“类数组对象”行为让我感到困惑:

var arrayLikeObj = {
    0: 'Marty',
    1: 78,
    2: 42,
    3: ['Tim', 'Eric', 'Phil'],
    length: 4
};

我的理解是这里的长度属性与Array.prototype.length方法完全无关,是硬编码为了给对象赋予必要的类似数组的属性。

然而,当我像这样pop数组对象时:

console.log(Array.prototype.pop.call(arrayLikeObj));

...它的长度属性已经减少了!

console.log(arrayLikeObj) // Object {0: "Marty", 1: 78, 2: 42, length: 3} 

这怎么可能!?

Array.prototype.length 是否会覆盖对象中现有的 length 属性,将其变成一个 length 方法呢?

更让我困惑的是,当我声明一个没有硬编码 length 属性的对象并调用相同的 pop 方法时:

var arrayLikeObj = {
        0: 'Marty',
        1: 78,
        2: 42,
        3: ['Tim', 'Eric', 'Phil']
    };

console.log(Array.prototype.pop.call(arrayLikeObj));
console.log(arrayLikeObj);

返回的对象已被分配长度为0:
{0: "Marty", 1: 78, 2: 42, 3: Array[3], length: 0}

我非常想了解这里正在发生的事情。


因为这就是该方法的作用。它被描述为修改给定的this对象上的.length属性。ECMAScript 5 - 15.4.4.6 Array.prototype.pop 如果没有.length,则会得到默认值0。*"如果长度为零, a. 使用参数“length”,0和true调用O的[[Put]]内部方法; b. 返回未定义"* - cookie monster
请注意,大多数(如果不是全部)Array.prototype方法都有以下版本:“pop函数是有意通用的;它不要求其this值为Array对象。因此,它可以被转移到其他类型的对象中以用作方法。” - cookie monster
1个回答

3
Array.prototype.pop方法会为对象创建一个length属性。
此操作发生在步骤4.a和5.d中。在您发布的第二个情况中,请注意[[Get]]内部方法返回undefined(因为没有length属性),并且ToUint32(undefined)undefined先转换为NaN,然后将NaN转换为0
参考链接:http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接