对array构造函数创建的未定义数组执行forEach操作
forEach on array of undefined created by Array constructor
我只是想知道为什么不可能使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的数组,这不是问题,但对于更大的数组,这将是丑陋的。
为什么在未定义值的数组中循环出现问题?
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
查看.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);
}
}
};
因此,您可以看到,方法确实遍历整个Array (根据规范),但它只在成员实际存在时调用回调。它通过使用
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)
创建Array时,它创建了一个没有任何成员的Array,但是.length
设置为5
。这是一个稀疏数组的例子(在这个例子中非常稀疏)。因为in
找不到任何索引,所以永远不会调用回调。
您可以使用Array.from
创建一个数组并传递lambda函数,该函数将在数组中的每个项目上调用。
const arr = Array.from(
{ length: 5 },
() => 0
)
console.log(arr)
其他答案解释了问题,但没有提供解决方案。
ES6扩展语法用undefined
填充稀疏值。Array也是如此。apply(null, sparseArray),它具有在旧浏览器中工作的好处,但需要更多的工作来理解。
const sparseArray = new Array(5);
const unsparseArray1 = Array.apply(null, sparseArray);
const unsparseArray2 = [...sparseArray];
function arrayApply() {
// ES5 forEach works with either approach
unsparseArray1.forEach(function(elem, index, array) {
console.log(index);
});
}
function es6Spread() {
// Lodash each works with either approach
_.each(unsparseArray2, function(elem, index, array) {
console.log(index);
});
}
<html><head>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<title>Making sparse arrays unsparse</title>
</head><body>
<p><button onclick="arrayApply();">Array.apply(null, sparseArray)</button></p>
<p><button onclick="es6Spread();">[...sparseArray]</button></p>
</body>
</html>
在我的情况下,我正在寻找一个优雅的解决方案来创建从0
到X
开始的数字数组。
以一种优雅的方式使用箭头函数,它出现了一行代码
const arrayLength = 10;
const arrayOfDigits = Array.apply(null, Array(arrayLength)).map((_, index) => index);
在我看来是一个相当复杂的代码,比一个带有for
循环的单独代码块要复杂得多。
- JavaScript:只有当数组中的所有项都为true时才执行函数
- 如果数组仍在执行,async.forEach()将运行我添加到数组中的新元素
- Var工作,但在使用数组执行相同操作时停止
- 执行过滤对象数组的方法
- 使用数组表示法对多个字段执行jQuery日期选择器
- Bluebird中承诺链数组的串行执行
- 使用Node中的Q promise库对值数组顺序调用/执行相同的函数;并返回带有结果的新数组/集合
- 如何对jquery数组中的项执行函数
- Promise和Promise.all(数组)在数组实现之前执行
- 如何在不选择模式配置参数的情况下,使用mongoose在MongoDB模式实例化中的关联数组/对象中执行foreach
- 如何按顺序执行承诺数组
- 对javascript对象数组执行数学运算
- 从JavaScript数组执行多个回调
- 关联数组执行起来像散列表吗?
- 在Javascript中对Integer数组执行计算
- 获取setInterval以根据数组执行一定次数的操作
- 函数数组-执行单个函数
- 对array构造函数创建的未定义数组执行forEach操作
- 为什么我在为带有 parse.com 的数组执行 fetchAll 时出现错误
- JavaScript引擎是否对多维数组执行任何优化