Javascript 数组中的孔与未定义的孔及映射函数

Javascript 数组中的孔与未定义的孔及映射函数,javascript,arrays,Javascript,Arrays,我知道在数组上,未定义的索引不同于显式分配了“未定义”值的数组索引(是吗?)。然而,如何区分数组中的孔和未定义的值呢 以下代码: foo.js 。。。运行时产生: $ node foo.js A hole the same as undefined? yes f called on [undefined] f called on [3] f called on [4] 。。。将map替换为forEach时,类似的结果也会出现。中的操作符会告诉您索引是否已实际分配给: a=[] a[5]=w

我知道在数组上,未定义的索引不同于显式分配了“未定义”值的数组索引(是吗?)。然而,如何区分数组中的孔和未定义的值呢

以下代码:

foo.js

。。。运行时产生:

$ node foo.js 
A hole the same as undefined? yes
f called on [undefined]
f called on [3]
f called on [4]

。。。将
map
替换为
forEach

时,类似的结果也会出现。中的
操作符会告诉您索引是否已实际分配给:

a=[]
a[5]=window.foo
文件。写(a[4]+“
”) 文件。写(a[5]+“
”) 文件。书写((a中的4)+“
”) 文档。写((5 in a)+“
”)
你所说的“洞”并不完全是一个洞:

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
要获得带有孔的数组,可以手动删除属性,也可以从数组(N)开始并用值填充某些索引,或者使用push/splice但不使用返回数组的方法。例如:

Array(2).concat([void(0)]).concat(Array(3)).concat([3]).concat(Array(2)).concat([4]);
精确地复制原始数组(它有长度10和10个自己的属性),尽管第一个和(数组(2))没有



编辑:上述内容在ExtendScript中进行了测试,但在最近的浏览器中并不正确(请参阅注释)。后来在Firefox中进行了测试,[,,,,,]确实没有自己的属性…

我从答案中得出结论,
forEach
map
等。方法不会在孔上调用,但可以在分配了
undefined
值的索引上调用,并且没有惯用的方法要求在后一种情况下不调用它们;我必须在作为参数传递给
forEach
map
@MarcusJuniusBrutus的函数中进行检查:是的,这是正确的
forEach
不关心为索引分配了什么,唯一重要的是是否在某个点定义了索引。您需要重新运行第一个代码段。这些是孔,
n
计数是
0
而不是
10
。或者您使用的是什么非ES5引擎?顺便说一句,没有理由让循环中的
中断
。这可能会导致错误(太小)的结果。感谢您的测试,我实际上使用的是ExtendScript(Adobe),它配备了…ES3,重新运行它总是会给出相同的答案:0。中断是正常的,因为首先解析自己的属性。是的,它给出了
0
,但您的注释声明:
n;//10:a有10个自己的属性,全部设置为未定义
。请修正。我最后的评论有一个错误:它总是给出10。尽管未定义属性,但它们拥有的属性与条目一样多。这是我文章的重点,但这可能是ExtendScript的一个特性,我没有在浏览器中进行测试。
Array(2).concat([void(0)]).concat(Array(3)).concat([3]).concat(Array(2)).concat([4]);