6

我正在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 的)中,我读到数组的长度被计算为所有属性的最大数值。那么,当它拥有的最大数值属性是 0 时,为什么它说长度是 5?谢谢!

4

4 回答 4

6

Javascript 的一个好处是它的语义在标准中得到了正式的和尽可能明确的定义。具体而言,第 15.4 节指出:

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

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

另请注意,大多数数组方法都是通用的,并且不具体“了解”有关数组的任何内容。他们可以操作任意对象,如果这样的对象恰好有一个名为 的属性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朋友们不会使用这些信息。

于 2013-04-07T10:54:59.963 回答
1

问题5. _

你这样做的第二个,Javascript 数组被填满了用undefined值初始化的槽。

所以打电话

a[5] = 5;

原因

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

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

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

.length7

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

[0, undefined, undefined, undefined, undefined]

.length5


实际上,正如评论中指出的那样,这似乎仍然是非常奇怪的行为。初始化任何索引时,之前的插槽实际上并没有被任何东西分配。它创建一个稀疏数组。但是话又说回来,如果我们删除最后两个条目,则只0剩下一个undefined6

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

于 2013-04-07T10:15:40.990 回答
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。

于 2013-04-07T10:29:26.330 回答
0

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

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

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

但这远不是最佳的,性能方面的。

于 2013-04-07T10:23:15.920 回答