So many loops in js, for for… in for… Of forEach, some of these loops feel very much the same and today we’re going to talk about the difference between a for loop and a forEach. Let’s discuss it from several dimensions:
for
Circulation andforEach
The essential difference between.for
Circulation andforEach
Grammatical differences.for
Circulation andforEach
Performance differences.
The essential difference
The for loop is a loop method that has been around since JS was invented. ForEach is an ES5 method for mounting iterable prototypes, such as Array Set Map. ForEach is an iterator that iterates through the iterable. So what are traversal, iteration, and iterable. Traversal: Refers to the behavior of regularly accessing each member of a data structure. Iteration: Iteration is a special form of recursion, a method provided by iterators that, by default, accesses the members of a data structure one by one in a certain order. Iteration is also a traversal behavior. Iterable: Iterable: Array Set Map String arguments NodeList: [Symbol. Iterator] : [Symbol. Iterator] Objects that contain them are considered iterable.
ForEach is an iterator. The essential difference between forEach and a for loop is that forEach iterates through an Array Set Map, whereas a for loop is a loop that iterates through an Array. To talk more about what an Iterator is, remember that Generator, when called, generates an Iterator Object that has a.next() method, Each call returns an object {value:value,done:Boolean}. Value returns the yield value. When yield ends,done becomes true. An iterator is a special kind of object. It is marked in the ES6 specification by the next() method that returns an object, and the iteration behavior is judged in done. Iterators perform traversal without exposing the internal representation. Look at the code
let arr = [1.2.3.4] // Iterable
let iterator = arr[Symbol.iterator]() // A call to symbol. iterator yields an iterator object
console.log(iterator.next()); // {value: 1, done: false} accesses the next method of the iterator object
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
Copy the code
We saw it. As long as it is can be iterative object, call the internal Symbol. The iterator will provide an iterator, and according to the iterator returned the next way to access to the internal, and this is for… Implementation principle of OF.
let arr = [1.2.3.4]
for (const item of arr) {
console.log(item); // 1, 2, 3, 4
}
Copy the code
Calling next returns the value of the object and stores it in item until value is undefined and out of the loop, all iterables are available for… Of consumption. Let’s look at the other iterables:
function num(params) {
console.log(arguments); // Arguments(6) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]
let iterator = arguments[Symbol.iterator]()
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
}
num(1.2.3.4)
let set = new Set('1234')
set.forEach(item= > {
console.log(item); // 1, 2, 3, 4
})
let iterator = set[Symbol.iterator]()
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
Copy the code
Iterators are generated when the Symbol. Iterator property of an iterable is called. ForEach generates an iterator, passing the value of each element in its internal callback function. ForEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach But using it on a Set Map gives an error, so I assume it’s the iterator called, calling next over and over, passing arguments to the callback function. Since I didn’t find the answer online, I don’t know what to say. If you have an answer, please leave me a message in the comment section.)
for
Circulation andforEach
Grammatical differences between
Knowing the essential differences, what grammatical differences do they have in the application process?
forEach
The parameters.forEach
Interrupts.forEach
Index cannot be reset when its element is deleted.for
A loop can control the start of a loop.
forEach
The parameters of the
Do we really know the full content of forEach’s feed? It looks something like this:
arr.forEach((self,index,arr) = >{},this)
Copy the code
Self: The element currently traversed by the array. By default, the array elements are fetched from left to right. Index: The index of the current element in the array. The first element is 0, and so on. Arr: array currently traversed. This: This points to in the callback function.
let arr = [1.2.3.4];
let person = {
name: 'Tech Straight Star'
};
arr.forEach(function (self, index, arr) {
console.log(The current element is${self}The index for${index}, belongs to an array${arr}`);
console.log(this.name+='nice');
}, person)
Copy the code
We can use ARR to implement array de-duplication:
let arr1 = [1.2.1.3.1];
let arr2 = [];
arr1.forEach(function (self, index, arr) {
arr.indexOf(self) === index ? arr2.push(self) : null;
});
console.log(arr2); / / [1, 2, 3]
Copy the code
forEach
The interrupt
In javascript, a break return continue is used to interrupt a function or break out of the loop. We use some interrupt behavior in the for loop, which is good for optimizing array traversal search. However, because forEach is an iterator, it can only be traversed in order, so the above interrupt behavior is not supported.
let arr = [1.2.3.4],
i = 0,
length = arr.length;
for (; i < length; i++) {
console.log(arr[i]); / / 1, 2
if (arr[i] === 2) {
break;
};
};
arr.forEach((self,index) = > {
console.log(self);
if (self === 2) {
break; / / an error
};
});
arr.forEach((self,index) = > {
console.log(self);
if (self === 2) {
continue; / / an error
};
});
Copy the code
What if I had to break out of the loop in forEach? Try /catch:
try {
var arr = [1.2.3.4];
arr.forEach(function (item, index) {
// Jump conditions
if (item === 3) {
throw new Error("LoopTerminates");
}
//do something
console.log(item);
});
} catch (e) {
if(e.message ! = ="LoopTerminates") throw e;
};
Copy the code
If a return is encountered, no error is reported, but it does not take effect
let arr = [1.2.3.4];
function find(array, num) {
array.forEach((self, index) = > {
if (self === num) {
return index;
};
});
};
let index = find(arr, 2);// undefined
Copy the code
forEach
Index cannot be reset when its element is deleted
In forEach we have no control over the index value, it just increments mindlessly until the length greater than the array jumps out of the loop. Therefore, it is not possible to delete itself to reset index.
let arr = [1.2.3.4]
arr.forEach((item, index) = > {
console.log(item); // 1, 2, 3, 4
index++;
});
Copy the code
Index does not change as it is added or subtracted from the function body. In real development, it is quite common to iterate through a number group and delete an item simultaneously, so be careful when using forEach for deletion.
for
A loop can control the start of a loop
As mentioned above, the starting point of forEach cycle can only be 0 without human intervention, while for cycle is different:
let arr = [1.2.3.4],
i = 1,
length = arr.length;
for (; i < length; i++) {
console.log(arr[i]) / / 2, 3, 4
};
Copy the code
The previous array traversal and delete spawning operation can be written as
let arr = [1.2.1],
i = 0,
length = arr.length;
for (; i < length; i++) {
// Delete all 1's in the array
if (arr[i] === 1) {
arr.splice(i, 1);
// reset I, otherwise I jumps one bit
i--;
};
};
console.log(arr); / / [2]
/ / equivalent to the
var arr1 = arr.filter(index= >index ! = =1);
console.log(arr1) / / [2]
Copy the code
for
Circulation andforEach
Performance difference of
For performance comparisons, we add a Map iterator, which generates new arrays just like the filter. For > forEach > Map in Chrome 62 and Node.js v9.1.0: The for loop is twice as fast as forEach, and forEach is about 20% faster than Map. Reason analysis for: The for loop has no additional function call stack or context, so it is the easiest to implement. ForEach: For forEach, its function signature contains parameters and context, so performance is lower than for loops. Map: The reason map is the slowest is that the map returns a new array, and the creation and assignment of an array results in the allocation of memory, thus incurs a high performance overhead. Nesting a map in a loop leads to more unnecessary memory consumption. When iterators are used to traverse an array, it is against design to use a map without returning a new array. I’ve seen a lot of people use maps just to iterate through groups of numbers in front-end co-development:
let data = []; Let data2 = [1, 2, 3]; data2.map(item=>data.push(item));Copy the code
At the end: This was a question I had in an interview, knowing only the grammar difference. Instead of further differentiating the similarities and differences in terms of iterables, iterators, generators, and performance, I wish I could have taken a simple problem and explained it in more detail so that you could understand it better.
If this article can help or inspire you, it will be my pleasure