The foolish and ignorant I was asked this question, head a blank, because at one point I think forEach just for the convenience of the syntactic sugar, writing created is also often used in business code, but no thought about the problem of it, the purpose of this paper is to record their journey, the author if some help to you it will be better.
So back to the title, first of all forEach can not use any means to jump out of the loop, want to know the answer to the question at this time can not continue to see.
Why is that? ForEach receives a function that takes two arguments, the first being the current element of the loop and the second being the corresponding index of that element.
Array.prototype.myForEach = function (fn) {
for (let i = 0; i < this.length; i++) {
fn(this[i], i, this); }}Copy the code
I don’t know if forEach is actually implemented this way, but this simple pseudocode does work for forEach, and it obviously doesn’t work out of the loop, because there’s no way to actually operate on the body of a for loop.
After reviewing the documentation, it turns out that the official definition of forEach isn’t the syntactic sugar I thought it was. The standard is that forEach executes the function you provide once forEach array element. The official document also says:
There is no other way to stop or break the loop than to throw an exception. If you need this behavior, the forEach() method is the wrong tool.
Throw an exception to break out of the foreach loop
let arr = [0.1."stop".3.4];
try {
arr.forEach(element= > {
if (element === "stop") {
throw new Error("forEachBreak");
}
console.log(element); // output 0, 1, no output
});
} catch (e) {
console.log(e.message); // forEachBreak
};
Copy the code
Can we assume that forEach can jump out of a loop and just throw an exception? In forEach, there is no design to interrupt the loop, and when you use a try-catch wrap, performance will inevitably decline when the loop body is too large, so throwing an exception can be used as a way to interrupt the forEach. But it’s not a silver bullet to solve the forEach problem.
Go back to the pseudocode I wrote at the beginning and make it a little better by adding a judgment on the passed function to the real for loop:
// forEach is not overwritten to avoid controversy
Array.prototype.myForEach = function (fn) {
for (let i = 0; i < this.length; i++) {
let ret = fn(this[i], i, this);
if (typeofret ! = ="undefined" && (ret == null || ret == false)) break; }}Copy the code
This way, we can loop out according to the return value:
let arr = [0.1."stop".3.4];
arr.myForEach(x= > {
if (x === 'stop') return false
console.log(x); // output 0, 1, no output
});
// return continues:
arr.myForEach(x= > {
if (x === 'stop') return
console.log(x); // 0 1 3 4
});
Copy the code
The documentation also mentions that forEach needs a synchronous function, meaning that unexpected results can occur when using asynchronous functions or promises as callbacks, so forEach should be used with caution.
Of course, using a simple for loop to complete everything is also one way, the code is written for people first, with the function of running on the machine, forEach is more convenient to use in many times, but it is also important to understand how JS design these tool functions under the premise of writing our business code.
We can use for… when iterating over groups of numbers. of.. , using for.. when traversing objects. in.. ForEach also lists some other utility functions in the forEach documentation, but I won’t expand them too much here:
Array.prototype.find()
Array.prototype.findIndex()
Array.prototype.map()
Array.prototype.filter()
Array.prototype.every()
Array.prototype.some()
Copy the code
How to choose and use the corresponding tool functions to deal with business logic more effectively according to different business scenarios is what we should really think about, perhaps this is also what we really want to investigate in the interview.