forEach 在 Array 构造函数创建的未定义数组上

新手上路,请多包涵

我只是想知道为什么不能在未定义的数组上创建 forEach。

代码:

 var arr = new Array(5); // [undefined x 5]

//ES5 forEach
arr.forEach(function(elem, index, array) {
    console.log(index);
});

//underscore each
_.each(arr, function(elem, index, array) {
    console.log(index);
});

这两个示例都不执行功能。

现在要制作 foreach,我必须制作:

 var arr = [0,0,0,0,0];

然后在上面制作forEach。

我正在尝试创建一个具有指定大小的数组并循环遍历它,避免 for 循环。我认为使用 forEach 比使用 for 循环更清楚。对于长度为 5 的数组,这不是问题,但是对于更大的数组,它会很丑陋。

为什么循环遍历未定义值的数组会出现问题?

原文由 Tukkan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 303
2 个回答

Array(5) 本质上等同于

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

在 javascript 中,更改数组的长度不会为其数字属性设置任何值,也不会在数组对象中定义这些属性。所以数字属性是未定义的,而不是具有未定义的值。您可以使用以下方法检查它:

 Object.keys(arr)

迭代时,javascript 会遍历数组的数字属性,因此如果这些属性不存在,则没有什么可迭代的。

您可以通过执行以下操作来检查它:

 var arr = Array(5)

//prints nothing
arr.forEach(function(elem, index, array) {
    console.log(index);
});

arr[3] = 'hey'
//prints only 'hey' even though arr.length === 5
arr.forEach(function(elem, index, array) {
    console.log(index);
});

以下代码:

 var arr = [undefined, undefined];

创建 length ===2 的数组并将 数值属性 0 和 1 设置为 undefined

原文由 soulcheck 发布,翻译遵循 CC BY-SA 3.0 许可协议

查看 .forEach() 的简化实现可能会有所帮助。

 Array.prototype.my_for_each = function(callback, thisArg) {
    for (var i = 0; i < this.length; i++) {
        if (i in this) {
            callback.call(thisArg, this[i], i, this);
        }
    }
};


所以你可以看到发生的事情是该方法 确实 迭代了整个数组 (根据规范) ,但它只在成员实际存在时调用回调。它通过使用 in 运算符查找属性 (索引) 来检查,该运算符测试对象是否具有或继承该属性。

如果 in 显示索引存在,则调用回调。


所以给定这个数组:

 var arr = ["foo", "bar", "baz"];

这将输出所有 3 个项目:

 arr.my_for_each(function(item) {
    console.log(item);
});
// "foo" "bar" "baz"

但是如果我们使用 delete 删除一个成员,它会在数组中留下一个空洞,现在将被忽略。

 delete arr[1];

arr.my_for_each(function(item) {
    console.log(item);
});
// "foo" "baz"


当您使用 Array(5) 创建一个数组时,它创建了一个没有任何成员的数组,但 .length 设置为 5 。所以这是一个稀疏数组的例子(在这个例子中非常稀疏)。因为 in 找不到任何索引,所以永远不会调用回调。

原文由 cookie monster 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题