forEach由Array构造函数创建的undefined数组

Tuk*_*kan 13 javascript arrays foreach undefined

我只是想知道为什么不能在未定义的数组上制作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);
});
Run Code Online (Sandbox Code Playgroud)

两个示例都不执行功能.

现在要做到foreach,我必须做:

var arr = [0,0,0,0,0];
Run Code Online (Sandbox Code Playgroud)

然后为它做每一个.

我试图创建一个具有指定大小的数组并循环它,避免for循环.我认为使用forEach比使用循环更清楚.对于长度为5的数组,这不是问题,但是对于更大的数组来说它会很难看.

为什么在循环未定义值数组时出现问题?

sou*_*eck 24

Array(5) 本质上相当于

var arr = []; 
arr.length = 5;
Run Code Online (Sandbox Code Playgroud)

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

Object.keys(arr)
Run Code Online (Sandbox Code Playgroud)

当迭代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);
});
Run Code Online (Sandbox Code Playgroud)

以下代码:

var arr = [undefined, undefined];
Run Code Online (Sandbox Code Playgroud)

创建和数组length ===2并将数字属性0和1都设置为undefined.


coo*_*ter 5

查看 的简化实现.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);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

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

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


所以给定这个数组:

var arr = ["foo", "bar", "baz"];
Run Code Online (Sandbox Code Playgroud)

这将输出所有 3 个项目:

arr.my_for_each(function(item) {
    console.log(item);
});
// "foo" "bar" "baz"
Run Code Online (Sandbox Code Playgroud)

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

delete arr[1];

arr.my_for_each(function(item) {
    console.log(item);
});
// "foo" "baz"
Run Code Online (Sandbox Code Playgroud)

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