Array.pop()乱码数组的长度吗?

时间:2013-04-07 10:07:49

标签: javascript

我在ideone中尝试以下代码:

var a = [];
a[0] = 0;
a[5] = 5;
a[6] = undefined;
print("contents before popping:");
for(var e in a) print("\ta[", e, "] =", a[e]);
print("a.length =", a.length);
for (var i = 0; i < a.length; i++) 
    print("\ta.hasOwnProperty(", i, ") =", a.hasOwnProperty(i));

print("popping -->", a.pop());
print("popping -->", a.pop());
print("contents after popping:");
for(var e in a) print("\ta[", e, "] =", a[e]);
print("a.length =", a.length);
for (var i = 0; i < a.length; i++) 
    print("\ta.hasOwnProperty(", i, ") =", a.hasOwnProperty(i));

输出如下:

contents before popping:
    a[ 0 ] = 0
    a[ 5 ] = 5
    a[ 6 ] = undefined
a.length = 7
    a.hasOwnProperty( 0 ) = true
    a.hasOwnProperty( 1 ) = false
    a.hasOwnProperty( 2 ) = false
    a.hasOwnProperty( 3 ) = false
    a.hasOwnProperty( 4 ) = false
    a.hasOwnProperty( 5 ) = true
    a.hasOwnProperty( 6 ) = true
popping --> undefined
popping --> 5
contents after popping:
    a[ 0 ] = 0
a.length = 5
    a.hasOwnProperty( 0 ) = true
    a.hasOwnProperty( 1 ) = false
    a.hasOwnProperty( 2 ) = false
    a.hasOwnProperty( 3 ) = false
    a.hasOwnProperty( 4 ) = false

在我的JavaScript书(好吧,Crockford's)中,我读到数组的长度被计算为所有属性的最大数值。那么,为什么它的最大数值属性为0时长度为5?谢谢!

4 个答案:

答案 0 :(得分:6)

关于Javascript的一个好处是它的语义在形式上正如标准中定义的那样明确无误。具体来说,section 15.4表示:

  

length属性的值在数值上大于名称为数组索引的每个属性的名称;无论何时创建或更改Array对象的属性,都会根据需要调整其他属性以保持此不变量。

换句话说,每次更改数组时,其length都会被调整,但是,它只能保证大于max(indexes),并且不一定等于max(indexes)+1。例如,pop method总是删除length-1'元素并将length减1,无论数组实际包含多少元素。

另请注意,大多数数组方法都是通用的,并且不会“专门”了解有关数组的任何信息。它们可以操纵任意对象,如果这样的对象碰巧有一个名为length的属性,它将根据上述规则进行调整。考虑:

foo = {
    length: 100,
    99: 'hi'
}

alert([].pop.apply(foo)) // hi
alert(foo.length)        // 99

alert([].pop.apply(foo)) // undefined
alert(foo.length)        // 98

也就是说,在您的问题的上下文中,如何准确表示数组 - pop并且朋友不使用此信息。

答案 1 :(得分:1)

问题”是5作业

你做的第二个, Javascript数组充满了使用undefined值初始化的插槽。

所以打电话

a[5] = 5;

原因

[0, undefined, undefined, undefined, undefined, 5]

然后你也创建a[6]并用undefined初始化它,我们得到

[0, undefined, undefined, undefined, undefined, 5, undefined]
.length

7

现在我们调用 double .pop()(喜欢doublepop这个词)我们得到了

[0, undefined, undefined, undefined, undefined]
5

.length


实际上,正如评论中指出的那样,这似乎仍然是非常奇怪的行为。初始化任何索引时,之前的插槽实际上并没有被任何指定。它创建了一个稀疏数组。但话又说回来,如果我们删除最后两个条目,则只剩下一个值(0),后跟undefined个值(某种程度变为 real 值,可能是因为我们手动分配了6

我想我们需要一个实现大师:)

答案 2 :(得分:1)

  

“数组的长度计算为所有数值的最大值   属性“

这对于阵列的所有用途都不准确。如果为数组中的索引指定值,则会以这种方式工作,但如果您专门设置length或使用pop之类的方法则不行。

示例:

var a = [];
a.length = 5;

console.log("length =", a.length);

for (var i = 0; i < a.length; i++) 
  console.log("a.hasOwnProperty(", i, ") =", a.hasOwnProperty(i));

输出:

length = 5
a.hasOwnProperty(0) = false
a.hasOwnProperty(1) = false
a.hasOwnProperty(2) = false
a.hasOwnProperty(3) = false
a.hasOwnProperty(4) = false

现在你有一个没有任何项目的数组,但长度为5。

答案 3 :(得分:0)

问题实际上与您没有使用顺序索引而不是使用pop函数这一事实有关。您会注意到,在第一个长度打印时,数组的长度为7,但数组中只有3个项目。这与length返回最大索引/属性(+1)的事实有关,因为其余的值被设置为未定义的值。

你真的必须使用非顺序索引吗?如果是这样,您可能想尝试使用:

var counter = 0;
for (var i in a) {
    counter++;
  print("Property: "+i);
}
print("Total items: "+counter);

但这远不是最佳的,性能明智。