我理解数组上的map
is not called on undefined indexes并且我理解未定义的索引不同于明确分配了未定义的数组索引。价值(它是,不是吗?)。然而,如何区分数组中的空洞和undefined
值?
以下代码:
foo.js
var arr = [,,undefined,,,,3,,,4];
console.log("A hole the same as undefined? "+(arr[0]===undefined?"yes":"no"));
var _ignored = arr.map(function(x) {console.log("f called on ["+x+"]");});
...在跑步时产生:
$ node foo.js
A hole the same as undefined? yes
f called on [undefined]
f called on [3]
f called on [4]
...将map
替换为forEach
时,会有类似的结果。
答案 0 :(得分:6)
in
运算符会告诉您索引是否已实际分配给:
a = []
a[5] = window.foo
document.write(a[4] + "<br>")
document.write(a[5] + "<br>")
document.write((4 in a) + "<br>")
document.write((5 in a) + "<br>")
Javascript数组实际上是具有特殊length
属性的对象,而数组索引只是属性名称(事实上,它们甚至是字符串,而不是内部的数字)。所以上面的定义相当于:
a = {
5: window.foo,
length: 6
}
因此,与键相关的所有对象功能(如in
,hasOwnProperty
,Object.keys
)也适用于数组索引。
forEach
和其他迭代方法work by iterating from 0 to length-1 and checking if n-th index is actually present in the argument,他们不“知道”参数实际上是数组还是只是一个通用对象:
a = {1:'one', 5:'five', length:100};
[].forEach.call(a, function(x) {
document.write(x)
});
答案 1 :(得分:-1)
你所谓的“洞”并不是一个洞:
var a = [,,,,,,,,,,];
a.length; // 10
var n, k;
n=0; for (k in a){if (a.hasOwnProperty(k)){++n;}else{break;}};
n; // 10 : a has 10 own properties, all SET to undefined
现在删除所有属性,并重新计算
while (n--) delete a[n];
for (k in a){if (a.hasOwnProperty(k)){++n;}else{break;}};
n; // 0
a.length; // 10 : a is identical to Array(10), empty array of length 10
要获取带有孔的数组,您可以手动删除属性,或者使用Array(N)开始并使用值填充一些索引,或使用push / splice但不使用返回数组的方法。例如:
Array(2).concat([void(0)]).concat(Array(3)).concat([3]).concat(Array(2)).concat([4]);
完全重现你的原始数组(它有10个长度和10个自己的属性),虽然第一个summand(Array(2))没有。
编辑:以上是在ExtendScript中测试的,在最近的浏览器中并不是这样(参见评论)。之后在Firefox中测试过并且[,,,,,,]确实没有自己的属性......