一站式采购平台官网,wordpress 删除 分类存档,免费做公司电子画册的网站,php商城网站开发报告给大家推荐一个实用面试题库
1、前端面试题库 #xff08;面试必备#xff09; 推荐#xff1a;★★★★★
地址#xff1a;web前端面试题库
老实说我不喜欢用forEach#xff0c;因为它导致的一些bug总是这么不经意#xff0c;盘点我不喜欢的原因
原因一面试必备 推荐★★★★★
地址web前端面试题库
老实说我不喜欢用forEach因为它导致的一些bug总是这么不经意盘点我不喜欢的原因
原因一不支持处理异步函数
先看一个例子
async function test() {let arr [3, 2, 1]arr.forEach(async item {const res await mockSync(item)console.log(res)})console.log(end)
}function mockSync(x) {return new Promise((resolve, reject) {setTimeout(() {resolve(x)}, 1000 * x)})
}
test()
我们期望的结果是:
3
2
1
end但是实际上会输出:end
1
2
3JavaScript中的forEach()方法是一个同步方法它不支持处理异步函数。如果你在forEach中执行了异步函数forEach()无法等待异步函数完成它会继续执行下一项。这意味着如果在forEach()中使用异步函数无法保证异步任务的执行顺序。
替代forEach的方式
1.方式一
可以使用例如map()、filter()、reduce()等它们支持在函数中返回Promise并且会等待所有Promise完成。
使用map()和Promise.all()来处理异步函数的示例代码如下
const arr [1, 2, 3, 4, 5];async function asyncFunction(num) {return new Promise((resolve, reject) {setTimeout(() {resolve(num * 2);}, 1000);});
}const promises arr.map(async (num) {const result await asyncFunction(num);return result;
});Promise.all(promises).then((results) {console.log(results); // [2, 4, 6, 8, 10]
});由于我们在异步函数中使用了await关键字map()方法会等待异步函数完成并返回结果因此我们可以正确地处理异步函数。
方式二 使用for循环来处理异步函数
const arr [1, 2, 3, 4, 5];async function asyncFunction(num) {return new Promise((resolve, reject) {setTimeout(() {resolve(num * 2);}, 1000);});
}async function processArray() {const results [];for (let i 0; i arr.length; i) {const result await asyncFunction(arr[i]);results.push(result);}console.log(results); // [2, 4, 6, 8, 10]
}processArray();原因二无法捕获异步函数中的错误
如果异步函数在执行时抛出错误forEach()无法捕获该错误。这意味着即使在异步函数中出现错误forEach()仍会继续执行。
原因三除了抛出异常以外没有办法中止或跳出 forEach() 循环
forEach()方法不支持使用break或continue语句来跳出循环或跳过某一项。如果需要跳出循环或跳过某一项应该使用for循环或其他支持break或continue语句的方法。
原因四forEach 删除自身元素index不可被重置
在forEach中我们无法控制 index 的值它只会无脑的自增直至大于数组的 length 跳出循环。所以也无法删除自身进行index重置先看一个简单例子
let arr [1,2,3,4]
arr.forEach((item, index) {console.log(item); // 1 2 3 4index;
});原因五this指向问题
在forEach()方法中this关键字引用的是调用该方法的对象。但是在使用普通函数或箭头函数作为参数时this关键字的作用域可能会出现问题。在箭头函数中this关键字引用的是定义该函数时所在的对象。在普通函数中this关键字引用的是调用该函数的对象。如果需要确保this关键字的作用域正确可以使用bind()方法来绑定函数的作用域。以下是一个关于forEach()方法中this关键字作用域问题的例子
const obj {name: Alice,friends: [Bob, Charlie, Dave],printFriends: function () {this.friends.forEach(function (friend) {console.log(this.name is friends with friend);});},
};
obj.printFriends();在这个例子中我们定义了一个名为obj的对象它有一个printFriends()方法。在printFriends()方法中我们使用forEach()方法遍历friends数组并使用普通函数打印每个朋友的名字和obj对象的name属性。但是当我们运行这个代码时会发现输出结果为
undefined is friends with Bob
undefined is friends with Charlie
undefined is friends with Dave这是因为在forEach()方法中使用普通函数时该函数的作用域并不是调用printFriends()方法的对象而是全局作用域。因此在该函数中无法访问obj对象的属性。
为了解决这个问题可以使用bind()方法来绑定函数的作用域或使用箭头函数来定义回调函数。以下是使用bind()方法解决问题的代码示例
const obj {name: Alice,friends: [Bob, Charlie, Dave],printFriends: function () {this.friends.forEach(function (friend) {console.log(this.name is friends with friend);}.bind(this) // 使用bind()方法绑定函数的作用域);},
};
obj.printFriends();在这个例子中我们使用bind()方法来绑定函数的作用域将该函数的作用域绑定到obj对象上。运行代码后输出结果为
Alice is friends with Bob
Alice is friends with Charlie
Alice is friends with Dave通过使用bind()方法来绑定函数的作用域我们可以正确地访问obj对象的属性。
另一种解决方法是使用箭头函数。由于箭头函数没有自己的this它会继承它所在作用域的this。因此在箭头函数中this关键字引用的是定义该函数时所在的对象。代码略
原因六 forEach性能比for循环低
forfor循环没有额外的函数调用栈和上下文所以它的实现最为简单。forEach对于forEach来说它的函数签名中包含了参数和上下文所以性能会低于 for 循环。
原因七会跳过已删除或者未初始化的项
// 跳过未初始化的值
const array [1, 2, /* empty */, 4];
let num 0;array.forEach((ele) {console.log(ele);num;
});console.log(num:,num);// 1
// 2
// 4
// num: 3// 跳过已删除的值
const words [one, two, three, four];
words.forEach((word) {console.log(word);if (word two) {// 当到达包含值 two 的项时整个数组的第一个项被移除了// 这导致所有剩下的项上移一个位置。因为元素 four 正位于在数组更前的位置所以 three 会被跳过。words.shift(); //one 将从数组中删除}
}); // one // two // fourconsole.log(words); // [two, three, four]
原因八forEach使用不会改变原数组
forEach() 被调用时不会改变原数组也就是调用它的数组。但是那个对象可能会被传入的回调函数改变
// 例子一
const array [1, 2, 3, 4];
array.forEach(ele { ele ele * 3 })
console.log(array); // [1,2,3,4]// 解决方式改变原数组
const numArr [33,4,55];
numArr.forEach((ele, index, arr) {if (ele 33) {arr[index] 999}
})
console.log(numArr); // [999, 4, 55]// 例子二
const changeItemArr [{name: wxw,age: 22
}, {name: wxw2,age: 33
}]
changeItemArr.forEach(ele {if (ele.name wxw2) {ele {name: change,age: 77}}
})
console.log(changeItemArr); // [{name: wxw, age: 22},{name: wxw2, age: 33}]// 解决方式
const allChangeArr [{ name: wxw, age: 22}, { name: wxw2, age: 33}]
allChangeArr.forEach((ele, index, arr) {if (ele.name wxw2) {arr[index] {name: change,age: 77}}
})
console.log(allChangeArr); // // [{name: wxw, age: 22},{name: change, age: 77}]好了我还是使用for...of去替代forEach吧 给大家推荐一个实用面试题库
1、前端面试题库 面试必备 推荐★★★★★
地址web前端面试题库