How to select the traversal mode of array from the perspective of performance

Keywords: Javascript

preface

This paper describes several array traversal methods commonly used in JS and performance analysis and comparison.

If this article helps you, ❤️ Follow + like ❤️ Encourage the author, the official account and the first time to get the latest articles.

Array method

JavaScript has provided many array methods up to now. The following figure covers most of the array methods. This article mainly talks about the array traversal methods and their respective performance. There are so many methods. How to select the method with the best performance is very helpful to our development.

Array traversal method

for

The standard for loop statement is also the most traditional loop statement

var arr = [1,2,3,4,5]
for(var i=0;i<arr.length;i++){
  console.log(arr[i])
}

The simplest traversal method is also the most frequently used, with good performance, but it can also be optimized

Optimized for loop statement

var arr = [1,2,3,4,5]
for(var i=0,len=arr.length;i<len;i++){
  console.log(arr[i])
}

Use temporary variables to cache the length to avoid repeatedly obtaining the array length, especially when the array length is large.

This method is basically the highest performance of all loop traversal methods

forEach

Common forEach

Run the given function on each element in the array without return value. It is often used to traverse the elements

var arr5 = [10,20,30]
var result5 = arr5.forEach((item,index,arr)=>{
    console.log(item)
})
console.log(result5)
/*
10
20
30
undefined   The method has no return value
*/

Array's own foreach loop is frequently used. In fact, its performance is weaker than that of ordinary for loop

Prototype forEach

Because foreach comes with Array type, some non Array types cannot be used directly (such as NodeList), so this variant is available. Using this variant can make similar arrays have foreach function.

const nodes = document.querySelectorAll('div')
Array.prototype.forEach.call(nodes,(item,index,arr)=>{
  console.log(item)
})

The actual performance is weaker than ordinary foreach

for...in

Traverse the division of an object in any order Symbol Outside enumerable Properties, including inherited enumerable properties.

It is commonly used to traverse objects, including the names of non integer types and the attributes on the inherited prototype chain. For example, objects created by Array and Object using built-in constructors will inherit from the non enumerable properties of Object.prototype and String.prototype, so they cannot be traversed

var arr = [1,2,3,4,5]
for(var i in arr){
  console.log(i,arr[i])
}  //Here i is the object attribute, that is, the subscript of the array
/**
0 1
1 2
2 3
3 4
4 5 **/

Most people like this method, but its performance is not very good

for...of (cannot traverse object)

Create an iteration loop on the iteratable object (with iterator interface) (Array, Map, Set, String, arguments), call the custom iteration hook, and execute the statement for the value of each different attribute. The object cannot be traversed

let arr=["front end","Nanjiu","ssss"];
    for (let item of arr){
        console.log(item)
    }
//Front end Nanjiu ssss

//Traversal object
let person={name:"Nanjiu",age:18,city:"Shanghai"}
for (let item of person){
  console.log(item)
}
// We found it impossible. We can use it with Object.keys
for(let item of Object.keys(person)){
    console.log(person[item])
}
// Nanjiu 18 Shanghai

This method is used in es6. Its performance is better than forin, but it is still not as good as ordinary for loops

map

map: you can only traverse the array without interruption. The return value is the modified array.

let arr=[1,2,3];
const res = arr.map(item=>{
  return res+1
})
console.log(res) //[2,3,4]
console.log(arr) // [1,2,3]

every

Run the given function for each item in the array. If the function returns true for each item, the function returns true

var arr = [10,30,25,64,18,3,9]
var result = arr.every((item,index,arr)=>{
      return item>3
})
console.log(result)  //false

some

Run the given function for each item in the array. If one item of the function returns true, it will return true, and all items return false before returning false

var arr2 = [10,20,32,45,36,94,75]
var result2 = arr2.some((item,index,arr)=>{
    return item<10
})
console.log(result2)  //false

reduce

The reduce() method executes a reducer function (executed in ascending order) provided by you for each element in the array, and summarizes the results into a single return value

const array = [1,2,3,4]
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));

filter

Running a given function on each item in the array returns an array of items that satisfy the function

// filter returns a new array of array items that meet the requirements
var arr3 = [3,6,7,12,20,64,35]
var result3 = arr3.filter((item,index,arr)=>{
    return item > 3
})
console.log(result3)  //[6,7,12,20,64,35]

performance testing

Tool test

Test with tools performance analysis The results are shown in the figure below

Manual test

We can also test with our own code:

//Test function
function clecTime(fn,fnName){
        const start = new Date().getTime()
        if(fn) fn()
        const end = new Date().getTime()
        console.log(`${fnName}Execution time:${end-start}ms`)
}

function forfn(){
  let a = []
  for(var i=0;i<arr.length;i++){
    // console.log(i)
    a.push(arr[i])
  }
}
clecTime(forfn, 'for')   //for execution time: 106ms

function forlenfn(){
  let a = []
  for(var i=0,len=arr.length;i<len;i++){
    a.push(arr[i])
  }
}
clecTime(forlenfn, 'for len')   //for len execution time: 95ms

function forEachfn(){
  let a = []
  arr.forEach(item=>{
    a.push[item]
  })
}
clecTime(forEachfn, 'forEach')   //forEach execution time: 201ms

function forinfn(){
  let a = []
  for(var i in arr){
    a.push(arr[i])
  }
}
clecTime(forinfn, 'forin') //forin execution time: 2584ms (outrageous)

function foroffn(){
  let a = []
  for(var i of arr){
    a.push(i)
  }
}
clecTime(foroffn, 'forof') //forof execution time: 221ms

//  ... others can be tested by themselves

Result analysis

Through the tool and manual test, it is found that the results are basically the same. The speed of array traversal of each method: the traditional for loop is the fastest and for in is the slowest

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

Suggested usage of javascript native traversal method:

  • Traversing an array with a for loop
  • Traversing objects with for...in
  • Traversing class array objects with for...of (ES6)
  • Get the collection of object attribute names with Object.keys()

Why is for... in slow?

Because the for...in syntax is the first JavaScript statement that can iterate over object keys, looping over object keys ({}) is different from looping over arrays ([]), and the engine will perform some extra work to track the iterated properties. Therefore, it is not recommended to use for...in to traverse the array

Recommended reading

These browser interview questions, see how many you can answer?
This time it takes you through front-end local storage
Interviewer: tell me the difference between front-end routing and back-end routing
Prototype and prototype chain of JavaScript
Javascript deep scope and closure
this points to call,apply,bind

I think the article is good. You can praise it_ In addition, please pay attention to message exchange ~

Posted by smnovick on Tue, 23 Nov 2021 07:47:41 -0800