5 factions arrive on the battlefield: for, Foreach, Map, for… in , for… of

Self-introduction

for

I am one of the earliest lords in the world of traversal. Everyone here should call me grandpa. I can meet most of the needs of developers.

// go through the number group
let arr = [1.2.3];
for(let i = 0; i < arr.length; i++){console.log(i)          // Index array subscript
    console.log(arr[i])     // The element corresponding to the array subscript
}

// Iterate over the object
let profile = {name:"April".nickname:"Twenty-seven minutes".country:"China"};
for(let i = 0, keys=Object.keys(profile); i < keys.length; i++){console.log(keys[i])            // The key of the object
    console.log(profile[keys[i]])   // The value of the key of the object
}

// Iterate over the string
let str = "abcdef";
for(let i = 0; i < str.length ; i++){console.log(i)          // Index string subscript
    console.log(str[i])     // The element of the string subscript
}

// Iterate over the DOM node
let articleParagraphs = document.querySelectorAll('.article > p');
for(let i = 0; i<articleParagraphs.length; i++){ articleParagraphs[i].classList.add("paragraph");
    // Add a class attribute named "paragraph" to the p tag under the class named "article" node.
}
Copy the code

forEach

I’m an ES5 release. Callback is executed for each valid item in the array in ascending order, and deleted or uninitialized items are skipped (for example, on a sparse array). I’m an enhanced version of the for loop.

// go through the number group
let arr = [1.2.3];
arr.forEach(i= > console.log(i))

// logs 1
// logs 2
// logs 3
// Outputs the elements of the array directly

// Iterate over the object
let profile = {name:"April".nickname:"Twenty-seven minutes".country:"China"};
let keys = Object.keys(profile);
keys.forEach(i= > {
    console.log(i)              // The key of the object
    console.log(profile[i])     // The value of the key of the object
})
Copy the code

map

I’m also an ES5 release, and I can create a new array, the result of which is the return value of each element in the original array after calling the supplied function once.

let arr = [1.2.3.4.5];
let res = arr.map(i= > i * i);

console.log(res) // logs [1, 4, 9, 16, 25]
Copy the code

for… In the enumeration

I’m an ES5 release. Iterate through the enumerable properties of an object except Symbol in any order.

// Iterate over the object
let profile = {name:"April".nickname:"Twenty-seven minutes".country:"China"};
for(let i in profile){
    let item = profile[i];
    console.log(item)   // The key of the object
    console.log(i)      // The value of the key of the object

// go through the number group
let arr = ['a'.'b'.'c'];
for(let i in arr){
    let item = arr[i];
    console.log(item)   // The element corresponding to the array subscript
    console.log(i)      // Index array subscript

// Iterate over the string
let str = "abcd"
for(let i in str){
    let item = str[i];
    console.log(item)   // The element of the string subscript
    console.log(i)      // Index string subscript
}
Copy the code

for… Of the iteration

I’m an ES6 release. Create an iteration loop on iterable objects (including Array, Map, Set, String, TypedArray, Arguments, and so on), call custom iteration hooks, and execute statements for the values of each different property.

// Iterate over the array array
let arr = ['a'.'b'.'c'];
for(let item of arr){
    console.log(item)     
}
// logs 'a'
// logs 'b'
// logs 'c'

// Iterate over the string
let str = "abc";
for (let value of str) {
    console.log(value);
}
// logs 'a'
// logs 'b'
// logs 'c'

/ / iterative map
let iterable = new Map([["a".1], ["b".2], ["c".3]]
for (let entry of iterable) {
    console.log(entry);
}
// logs ["a", 1]
// logs ["b", 2]
// logs ["c", 3]

// Iterate through map to get key values
for (let [key, value] of iterable) {
    console.log(key)
    console.log(value);
}


/ / iteration set
let iterable = new Set([1.1.2.2.3.3.4]);
for (let value of iterable) {
    console.log(value);
}
// logs 1
// logs 2
// logs 3
// logs 4

// Iterate over DOM nodes
let articleParagraphs = document.querySelectorAll('.article > p');
for (let paragraph of articleParagraphs) {
    paragraph.classList.add("paragraph");
    // Add a class attribute named "paragraph" to the p tag under the class named "article" node.
}

// Iterates over arguments class array objects
(function() {
  for (let argument of arguments) {
    console.log(argument);
  }
})(1.2.3);
/ / logs:
/ / 1
/ / 2
/ / 3


// Iterate over an array of types
let typeArr = new Uint8Array([0x00.0xff]);
for (let value of typeArr) {
  console.log(value);
}
/ / logs:
/ / 0
/ / 255
Copy the code

After the first round of self-introduction and skills demonstration, we learned:

  • For statementIs the original loop statement. Define a variablei(numeric type, representing the index of an array), subject to certain conditions, yesiI’m going to add it up. The condition is usually the length of the loop object, and the loop is stopped when the length is exceeded. Matches because the object cannot determine the lengthObject.keys()Use.
  • forEachES5 is put forward. Claim to beFor statementThe enhanced version can be found more than itFor statementIt’s a lot easier to write. But it’s essentially a loop of an array.forEachThe callback function is executed once for each array element. That’s the array that’s calling it, so it doesn’t change the original array. The return value isundefine.
  • mapES5 is put forward. The callback function is called once for each element in the array, in order. Generates a new array without modifying the original array itself. The return value is a new array.
  • for... inES5 is put forward. Iterate over enumerable properties on an object, including properties on the prototype object, in any order, i.e., in an unfixed order. I is a string when you iterate over an array using the subscript as the key. It is built to iterate over object properties and is not recommended for use with arrays.
  • for... ofES6 is put forward. Only iterate over the iterable’s data.

Ability to identify

As a programmer, it’s not enough just to get to know them, to identify their strengths and weaknesses in actual development. Use them according to local conditions. Improving the overall performance of the program is where the power lies.

About jumping out of the loop

When certain conditions are met in a loop, it jumps out of the loop body, or it skips data that does not meet the conditions and continues to loop other data. It’s a common requirement. Common statements are break and continue.

Say the distinction of both simply, had reviewed with respect to.

  • breakStatements are statements that break out of the current loop and execute after the current loop;
  • continueThe statement terminates the current loop and continues the next loop;

Note: forEach and Map do not support breaking out of the loop body. The other three methods do.

How it works: Look at how forEach works to understand this problem.

Array.prototype. ForEach (callbackfn [, thisArg]{}Copy the code

Function passed in is the callback function here. It is definitely illegal to use break inside a callback, because break can only be used to break out of a loop, and the callback is not the body of the loop.

Using a return in a callback function simply returns the result to the parent function, the for loop, and does not end the for loop, so return is also invalid.

The map () in the same way.

map()Chain calls

The map() method is chain-callable, which means it can be easily used in conjunction with other methods. For example, reduce(), sort(), filter(). But there are no other ways to do this. ForEach () returns undefined, so it cannot be chained.

// Multiply the element by itself and sum.
let arr = [1.2.3.4.5];
let res1 = arr.map(item= > item * item).reduce((total, value) = > total + value);

console.log(res1) // logs 55 undefined"
Copy the code

for... inIt iterates through the properties on the prototype object

Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
var arr = ['a', 'b', 'c'];
arr.foo = 'hello
for (var i in arr) {
    console.log(i);
}
// logs
// 0
// 1
// 2
// foo
// arrCustom
// objCustom
Copy the code

In real development, however, we do not need properties on the prototype object. In this case we can use the hasOwnProperty() method, which returns a Boolean value indicating whether the object has the specified property in its own properties (that is, whether it has the specified key). As follows:

Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; var arr = ['a', 'b', 'c']; arr.foo = 'hello for (var i in arr) { if (arr.hasOwnProperty(i)) { console.log(i); }} // logs // 0 // 1 // 2 // foo // Can't get rid of the properties of the visible array itself. ForEach is recommendedCopy the code

For traversal of pure objects, select for.. In enumeration is more convenient; For array traversal, if you don’t need to know the index for.. An of iteration is more appropriate because it can also be broken; If you need to know the index, forEach() is more appropriate; For other strings, class array, type array iteration, for.. Be in the upper hand But note that older browsers are about compatibility.

performance

Interested readers can find a set of data to test their own, the article will directly give the results, and do the corresponding explanation.

for > for-of > forEach  > map > for-in
Copy the code
  • forThe loop is of course the easiest, because it doesn’t have any extra function call stacks and contexts;
  • for... ofYou can use it to iterate over members of any data structure that has an Iterator interface. It reads the key directly.
  • forEachBecause it’s actually a little bit more complicated than we think. It’s actuallyarray.forEach(function(currentValue, index, arr), thisValue)It is not the syntactic sugar of a normal for loop, and there are many parameters and contexts that need to be taken into account when executing, which can be slow;
  • map()The slowest, since its return value is a brand new array of equal length, array creation and assignment incur significant performance overhead.
  • for... inAll attributes of the object need to be exhausted, including custom added attributes can also be traversed. andfor... inThe key isStringType, there is a conversion process, relatively high overhead.

conclusion

In actual development, we need to combine semantics, readability, and program performance to choose which solution to use.

If you need to map an array to another array according to some rule, you should use a map.

If you need to do simple traversal, use forEach or for of.

If you need to iterate over an iterator, use for of.

If you need to filter out items that match the criteria, use Filterr.

If you need to map to a new array by rules and then filter by criteria, use a map and a filter.

In short, according to local conditions, according to the time. Don’t let performance get in the way of semantics and readability. In the actual development, let them play to their strengths and avoid their weaknesses, complementary advantages, let the program approach the best is what we should do.