Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Does Array.pop()混乱数组';长度是多少?_Javascript - Fatal编程技术网

Javascript Does Array.pop()混乱数组';长度是多少?

Javascript Does Array.pop()混乱数组';长度是多少?,javascript,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(

我正在用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));
在我的JavaScript书(Crockford的)中,我读到数组的长度被计算为所有属性中最大的数值。那么,为什么它说长度是5,而它最大的数值属性是0?谢谢

问题是分配
5

第二次执行此操作时,Javascript数组将被插槽填满,这些插槽将使用
未定义的值进行初始化

这么叫

a[5] = 5;
原因

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

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

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

[0, undefined, undefined, undefined, undefined]
.length
of5


事实上,正如评论中所指出的,这似乎仍然是非常奇怪的行为。在初始化任何索引时,之前的插槽实际上没有任何分配。它创建一个稀疏数组。但是,如果我们再次删除最后两个条目,则只剩下一个值(
0
),后面是
未定义的值(可能是因为我们手动分配了
6
,这些值以某种方式变成了实际值)


我想我们需要一位实现专家:)

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

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

var counter = 0;
for (var i in a) {
    counter++;
  print("Property: "+i);
}
print("Total items: "+counter);
但就性能而言,这远远不是最优的

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

这对于数组的所有用途都不准确。如果您为数组中的索引指定了一个值,但如果您专门设置
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));

现在您有了一个数组,其中没有任何项目,但长度是5。

Javascript的一个优点是,它的语义在标准中得到了正式且尽可能明确的定义。具体而言,缔约国指出:

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

换句话说,每次更改数组时,都会调整其
长度
,但是,它只能保证大于
max(index)
,而不一定等于
max(index)+1
。例如,始终删除
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
,朋友们不使用此信息。

数组没有填充,因为
hasOwnProperty
返回
false
我不确定中间值是否初始化为
undefined
,我认为
a
是一个稀疏数组。@lmsteffan你说得对,我现在被自己搞糊涂了。这似乎符合我的描述,但实际上,应该没有剩余的插槽。尽管如此,我可以想象解释是正确的,但浏览器区分“自动填充”未定义和明确设置的未定义。区别在于它是否算作“hasOwnProperty”。但这听起来像是一个很大的怪癖,甚至可能是一个bug。这在所有浏览器中都是一样的吗?您好,我对代码没有任何问题。这是纯粹的人工构造,因为我只是试图理解语言。我在寻找它为什么会这样工作的解释,而不是如何修复它。那么,我必须同意上面的答案,尽管我不确定所有浏览器中的行为是否相同。但问题仍然存在,为什么和在哪里成为具有
未定义
值的插槽
1…4
实际插槽?事实上,正如@lamsteffan正确指出的,我们只是在处理稀疏数组。@jAndy,我想Guffa是对的<代码>数组。拼接
和直接分配
长度
表现出相同的行为,原因似乎是
长度
在某个点被分配。@jAndy:未使用的插槽没有任何值,但是如果您试图从不存在的插槽读取,您会得到
未定义的
。例如
console.log([[42])显示
未定义的
@Guffa我知道。但是我很困惑,因为在我们对最后两个值进行
pop
之后,长度仍然是
5
。什么时候确切地获得
.length
品牌?嗯,我猜是因为作业,然后它就再也不会被重置了。。。好吧,这是有道理的:p@jAndy:pop
方法不关心空插槽。它根据
length
属性获取最后一项,并将
长度减少一。您甚至可以在任何具有
length
属性的对象上应用
pop
方法,它甚至不必是数组:除了您的示例之外,我一直在传递这个提琴来演示array.length何时不可靠。
length = 5
a.hasOwnProperty(0) = false
a.hasOwnProperty(1) = false
a.hasOwnProperty(2) = false
a.hasOwnProperty(3) = false
a.hasOwnProperty(4) = false
foo = {
    length: 100,
    99: 'hi'
}

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

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