Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Discover a good thing during the holidays and suddenly feel like I don't like to write another for loop


Jun 01, 2021 Article blog


Table of contents


Using a variety of traversal methods, it was found that it was still the fastest for execution. B ecause it is simple, there is no additional function call stack and context. B ut in the actual development, we can not only consider speed, but to combine semantics, readability and program performance, to choose which scenario to use. H ere's a look at for foreach map for...in , for...of five ways to live battle.

Introduce yourself

for

I was one of the first party traversal statements to appear, and all of you here need to call me Grandpa. I can meet the vast majority of developers' needs.

// 遍历数组
let arr = [1,2,3];
for(let i = 0;i < arr.length;i++){
    console.log(i) // 索引,数组下标
    console.log(arr[i]) // 数组下标所对应的元素
}


// 遍历对象
let profile = {name:"April",nickname:"二十七刻",country:"China"};
for(let i = 0, keys=Object.keys(profile); i < keys.length;i++){
    console.log(keys[i]) // 对象的键值
    console.log(profile[keys[i]]) // 对象的键对应的值
}


// 遍历字符串
let str = "abcdef";
for(let i = 0;i < str.length ;i++){
    console.log(i) // 索引 字符串的下标
    console.log(str[i]) // 字符串下标所对应的元素
}


// 遍历DOM 节点
let articleParagraphs = document.querySelectorAll('.article > p');
for(let i = 0;i<articleParagraphs.length;i++){
    articleParagraphs[i].classList.add("paragraph");
    // 给class名为“article”节点下的 p 标签添加一个名为“paragraph” class属性。
}

forEach

I was released in ES5 release. T he callback function is executed once in ascending order for each item in the array with a valid value, and those items that have been deleted or not initialized are skipped (for example, on a sparse array). I'm the enhanced version of the for loop.

// 遍历数组
let arr = [1,2,3];
arr.forEach(i => console.log(i))


// logs 1
// logs 2
// logs 3
// 直接输出了数组的元素


//遍历对象
let profile = {name:"April",nickname:"二十七刻",country:"China"};
let keys = Object.keys(profile);
keys.forEach(i => {
    console.log(i) // 对象的键值
    console.log(profile[i]) // 对象的键对应的值
})

map

I was also released in the ES5 version, and I can create a new array whose result is the return value after each element in the original array calls the provided 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]

for... in enumeration

I was released in ES5 release. Enumerated properties of an object other than Symbol are traversed in any order.

// 遍历对象
let profile = {name:"April",nickname:"二十七刻",country:"China"};
for(let i in profile){
    let item = profile[i];
    console.log(item) // 对象的键值
    console.log(i) // 对象的键对应的值


// 遍历数组
let arr = ['a','b','c'];
for(let i in arr){
    let item = arr[i];
    console.log(item) // 数组下标所对应的元素
    console.log(i) // 索引,数组下标


// 遍历字符串
let str = "abcd"
for(let i in str){
    let item = str[i];
    console.log(item) // 字符串下标所对应的元素
    console.log(i) // 索引 字符串的下标
}

for... of iteration

I was released in ES6 release. Create an iterative loop on an iterative object, including Array Map Set String TypedArray arguments and so on, call a custom iterative hook, and execute statements for the values of each of the different properties.

// 迭代数组数组
let arr = ['a','b','c'];
for(let item of arr){
    console.log(item)
}
// logs 'a'
// logs 'b'
// logs 'c'


// 迭代字符串
let str = "abc";
for (let value of str) {
    console.log(value);
}
// logs 'a'
// logs 'b'
// logs 'c'


// 迭代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]


// 迭代map获取键值
for (let [key, value] of iterable) {
    console.log(key)
    console.log(value);
}




// 迭代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


// 迭代 DOM 节点
let articleParagraphs = document.querySelectorAll('.article > p');
for (let paragraph of articleParagraphs) {
    paragraph.classList.add("paragraph");
    // 给class名为“article”节点下的 p 标签添加一个名为“paragraph” class属性。
}


// 迭代arguments类数组对象
(function() {
  for (let argument of arguments) {
    console.log(argument);
  }
})(1, 2, 3);
// logs:
// 1
// 2
// 3




// 迭代类型数组
let typeArr = new Uint8Array([0x00, 0xff]);
for (let value of typeArr) {
  console.log(value);
}
// logs:
// 0
// 255

After the first round of self-introductions and skills presentations, we learned:

  • for statement is the most primitive loop statement. D efine a variable i (number type, which represents the subscript of an array) and cycle i to add up according to certain conditions. T he condition is usually the length of the loop object, which stops when it exceeds the length. Use with Object.keys() because the object cannot judge the length.

  • forEach E S5 is presented. C laiming to be a reinforced version of a for statement, you can see that it is much simpler to write than for statement. B ut it is also essentially an array loop. forEach performs the callback function once per array element. T hat is, the array that calls it, therefore, does not change the original array. The return value is undefine

  • map E S5 is presented. C allback functions are called once callback sequentially for each element in the original array. A new array is generated without modifying the original array itself that called it. The return value is the new array.

  • for...in ES5 proposed. E numerateable properties on an object, including those on a prototype object, and traverse in any order, i.e. in an irregular order. W hen you traverse an array, you label the array as a key value, and i is a string type. It is built to traverse object properties and is not recommended for use with arrays.

  • for...of ES6. Only the data of the iterable object is traversed.

Capacity screening

As a programmer, it is not enough to just recognize them and identify their strengths and weaknesses in actual development. U se them according to local conditions, and avoid short. Improving the overall performance of the program is where the ability lies.

About jumping out of the loop body

Jump out of the loop body when certain conditions are met in the loop, or skip the data that does not meet the criteria to continue looping other data. i s a requirement that is often encountered. Common statements are break and continue

Simply put, the difference between the two, just review it.

  • break statement is a statement that jumps out of the current loop and executes the current loop;

  • continue statement terminates the current loop and proceeds to the next loop;

Note: forEach and map are not supported to jump out of the loop body, and the other three methods are supported.

Principle: If you look at forEach implementation works, you'll understand the problem.

Array.prototype.forEachcallbackfn [,thisArg]{

    
}

The incoming function is the callback function here. It is certainly illegal to use break in a callback function because break can only be used to jump out of a loop, and the callback function is not a loop body.

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

map() is the same.

map() chain call

map() method can be called in chains, which means that it can be easily used in conjunction with other methods. F or example: reduce() sort() filter() etc. B ut other methods don't do that. The return value of forEach() is undefined so it cannot be called in chains.

// 将元素乘以本身,再进行求和。
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"

for... In traverses 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

In practice, however, we don't need properties on prototype objects. I n this case, we can use hasOwnProperty() method, which returns a Boolean value indicating whether the object has a specified property in its own property (that is, whether there is a 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


// 可见数组本身的属性还是无法摆脱。此时建议使用 forEach

For the traversal of a pure object, select for..in enumeration is more convenient; for array traversal, if you don't need to know the index for..of iterations are more appropriate because they can also be interrupted, forEach() is more appropriate if you need to know the index, and for other strings, class arrays, iterations of type arrays, for..of has the upper hand. Note, however, that lower-version browsers are matching.

performance

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

for > for-of > forEach > map > for-in

- for loop is of course the simplest because it does not have any additional function call stacks and contexts;

  • for...of can be used to iterate members as long as it has a data structure with an Iterator interface. It reads the key value directly.

  • forEach because it's actually more complex than we thought, it's actually array.forEach(function(currentValue, index, arr), thisValue) It's not an ordinary for loop of grammatical sugar, and there are many parameters and contexts to consider when executing, which can drag on chronic energy;

  • map() is the slowest because its return value is an entirely new array of equal lengths, and array creation and assignment incur significant performance overhead.

  • for...in requires that all properties of the object, including custom added properties, also be traversed. A nd for...in key of in is a String type, has a conversion process, and is expensive.

summary

In the actual development, we want to combine semantics, readability and program performance, to choose which scheme to use?

  • If you need to map an array to another array according to one rule, you should use map .

  • If you need a simple traversal, use forEach or for of .

  • If you need to traverse the iterator, use for of .

  • If you need to filter out eligible items, use filterr

  • If you need to map to a new array according to the rules and filter according to the criteria, add a map and a filter

All in all, to be flexible application, according to local conditions, different environments to choose the right syntax. D on't ignore semantics and readability by over-pursuing performance. Under your rule, the five of them can only play to their strengths, no one wants to dominate.

At the end of the day, recommend a course on Java

Java tutorial: https://www.w3cschool.cn/java/

Java Microsyscope: https://www.w3cschool.cn/minicourse/play/javaminicourse

Source: www.toutiao.com/a6842942752037011976/