A brief discussion on several common methods of traversing arrays and objects in JavaScript

青灯夜游
Release: 2021-06-25 11:21:57
forward
2670 people have browsed it

Arrays and objects play a vital role in various programming languages. This article will introduce to you the commonly used array traversal and object traversal methods in JavaScript, the differences between each method, and what to pay attention to when using them. matter.

A brief discussion on several common methods of traversing arrays and objects in JavaScript

Array traversal

With the continuous development of JS, there are more than ten traversal methods as of the ES7 specification. The following is a group of methods with similar functions to introduce the common traversal methods of arrays.

for, forEach, for...of

const list = [1, 2, 3, 4, 5, 6, 7, 8,, 10, 11]; for (let i = 0, len = list.length; i < len; i++) { if (list[i] === 5) { break; // 1 2 3 4 // continue; // 1 2 3 4 6 7 8 undefined 10 11 } console.log(list[i]); } for (const item of list) { if (item === 5) { break; // 1 2 3 4 // continue; // 1 2 3 4 6 7 8 undefined 10 11 } console.log(item); } list.forEach((item, index, arr) => { if (item === 5) return; console.log(index); // 0 1 2 3 5 6 7 9 10 console.log(item); // 1 2 3 4 6 7 8 10 11 });
Copy after login

Summary

  • All three are basic traversal of the array from left to right
  • forEach cannot break out of the loop; for and for..of can use break or continue to skip or interrupt.
  • for ...of directly accesses the actual element. for traverses the array index, and the forEach callback function has richer parameters, and elements, indexes, and original arrays can all be obtained.
  • for ...of and for will also be executed if there are empty elements in the array.

some、every

const list = [ { name: '头部导航', backward: false }, { name: '轮播', backward: true }, { name: '页脚', backward: false }, ]; const someBackward = list.some(item => item.backward); // someBackward: true const everyNewest = list.every(item => !item.backward); // everyNewest: false
Copy after login

Summary

  • Both It is used for array condition judgment, and both return a Boolean value
  • Both can be interrupted
  • some If a certain element meets the condition, it returns true and the loop is interrupted; all elements are not If the condition is met, return false.
  • every is the opposite of some. If the beneficial elements do not meet the conditions, false is returned and the loop is interrupted; if all elements meet the conditions, true is returned.

filter, map

const list = [ { name: '头部导航', type: 'nav', id: 1 },, { name: '轮播', type: 'content', id: 2 }, { name: '页脚', type: 'nav', id: 3 }, ]; const resultList = list.filter(item => { console.log(item); return item.type === 'nav'; }); // resultList: [ // { name: '头部导航', type: 'nav', id: 1 }, // { name: '页脚', type: 'nav', id: 3 }, // ] const newList = list.map(item => { console.log(item); return item.id; }); // newList: [1, empty, 2, 3] // list: [ // { name: '头部导航', type: 'nav', id: 1 }, // empty, // { name: '轮播', type: 'content', id: 2 }, // { name: '页脚', type: 'nav', id: 3 }, // ]
Copy after login

Summary

  • Both Generating a new array will not change the original array (excluding traversing the object array and operating the element object in the callback function)
  • Both will skip empty elements. Interested students can print it themselves
  • map will form a new array with the return value of the callback function, and the length of the array will be the same as the original array.
  • filter will form a new array with elements that meet the conditions of the callback function. The length of the array is different from the original array.
  • The new array elements generated by map are customizable.
  • The new array elements generated by filter cannot be customized and are consistent with the corresponding original array elements.

find、findIndex

const list = [ { name: '头部导航', id: 1 }, { name: '轮播', id: 2 }, { name: '页脚', id: 3 }, ]; const result = list.find((item) => item.id === 3); // result: { name: '页脚', id: 3 } result.name = '底部导航'; // list: [ // { name: '头部导航', id: 1 }, // { name: '轮播', id: 2 }, // { name: '底部导航', id: 3 }, // ] const index = list.findIndex((item) => item.id === 3); // index: 2 list[index].name // '底部导航';
Copy after login

Summary

  • Both is used to find array elements.
  • The find method returns the value of the first element in the array that satisfies the callback function. Returns undefined if it does not exist.
  • findIndex It returns the index of the element found in the array instead of its value, returning -1 if it does not exist.

reduce, reduceRight

The reduce method receives two parameters, the first parameter is the callback function (callback), the second parameter The first parameter is the initial value (initialValue).

reduceRight method is completely consistent with it except that it is in the opposite direction of reduce execution (from right to left).

The callback function receives four parameters:

  • accumulator: MDN is interpreted as an accumulator, but I think it is inappropriate. According to my understanding, it should be as of the current element, all previous elements The array elements are processed by the callback function to accumulate the results.
  • current: The array element currently being executed.
  • currentIndex: The array element index currently being executed.
  • sourceArray: The original array, which is the array where the reduce method is called.
If no initial value is passed in, the reduce method will execute the callback function starting from index 1. If an initial value is passed in, the callback function will be executed cumulatively from index 0 and based on the initial value.

Calculate the sum of a certain attribute of the object array

const list = [ { name: 'left', width: 20 }, { name: 'center', width: 70 }, { name: 'right', width: 10 }, ]; const total = list.reduce((currentTotal, item) => { return currentTotal + item.width; }, 0); // total: 100
Copy after login

Deduplication of the object array, and count the number of repetitions of each item

const list = [ { name: 'left', width: 20 }, { name: 'right', width: 10 }, { name: 'center', width: 70 }, { name: 'right', width: 10 }, { name: 'left', width: 20 }, { name: 'right', width: 10 }, ]; const repeatTime = {}; const result = list.reduce((array, item) => { if (repeatTime[item.name]) { repeatTime[item.name]++; return array; } repeatTime[item.name] = 1; return [...array, item]; }, []); // repeatTime: { left: 2, right: 3, center: 1 } // result: [ // { name: 'left', width: 20 }, // { name: 'right', width: 10 }, // { name: 'center', width: 70 }, // ]
Copy after login

Getting the maximum/minimum value of the object array

const list = [ { name: 'left', width: 20 }, { name: 'right', width: 30 }, { name: 'center', width: 70 }, { name: 'top', width: 40 }, { name: 'bottom', width: 20 }, ]; const max = list.reduce((curItem, item) => { return curItem.width >= item.width ? curItem : item; }); const min = list.reduce((curItem, item) => { return curItem.width <= item.width ? curItem : item; }); // max: { name: "center", width: 70 } // min: { name: "left", width: 20 }
Copy after login

reduce is very powerful. For more tricks, I recommend checking out this article "25 Advanced Array Reduce Usage You Have to Know"

Performance comparison

Having said so much, what is the difference in performance between these traversal methods? Let’s try it in the Chrome browser. I execute each loop 10 times, remove the maximum and minimum values, and take the average to reduce the error.

var list = Array(100000).fill(1) console.time('for'); for (let index = 0, len = list.length; index < len; index++) { } console.timeEnd('for'); // for: 2.427642822265625 ms console.time('every'); list.every(() => { return true }) console.timeEnd('every') // some: 2.751708984375 ms console.time('some'); list.some(() => { return false }) console.timeEnd('some') // some: 2.786590576171875 ms console.time('foreach'); list.forEach(() => {}) console.timeEnd('foreach'); // foreach: 3.126708984375 ms console.time('map'); list.map(() => {}) console.timeEnd('map'); // map: 3.743743896484375 ms console.time('forof'); for (let index of list) { } console.timeEnd('forof') // forof: 6.33380126953125 ms
Copy after login

It can be seen from the printing results that the for loop is the fastest and the for of loop is the slowest

Commonly used traversal termination and performance table comparison


是否可终止


** break continue return 性能(ms)
for 终止 ✅ 跳出本次循环 ✅ 2.42
forEach 3.12
map 3.74
for of 终止 ✅ 跳出本次循环 ✅ 6.33
some return true ✅ 2.78
every return false ✅ 2.75

最后,不同浏览器内核 也会有些差异,有兴趣的同学也可以尝试一下。

对象遍历

在对象遍历中,经常需要遍历对象的键、值,ES5 提供了 for...in 用来遍历对象,然而其涉及对象属性的“可枚举属性”、原型链属性等,下面将从 Object 对象本质探寻各种遍历对象的方法,并区分常用方法的一些特点。

for in

Object.prototype.fun = () => {};const obj = { 2: 'a', 1: 'b' };for (const i in obj) { console.log(i, ':', obj[i]);}// 1: b// 2: a// fun : () => {} Object 原型链上扩展的方法也被遍历出来for (const i in obj) { if (Object.prototype.hasOwnProperty.call(obj, i)) { console.log(i, ':', obj[i]); }}// name : a 不属于自身的属性将被 hasOwnProperty 过滤
Copy after login

小结

使用 for in 循环时,返回的是所有能够通过对象访问的、可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例。如果只需要获取对象的实例属性,可以使用 hasOwnProperty 进行过滤。

使用时,要使用(const x in a)而不是(x in a)后者将会创建一个全局变量。

for in 的循环顺序,参考【JavaScript 权威指南】(第七版)6.6.1。

  • 先列出名字为非负整数的字符串属性,按照数值顺序从最小到最大。这条规则意味着数组和类数组对象的属性会按照顺序被枚举。
  • 在列出类数组索引的所有属性之后,在列出所有剩下的字符串名字(包括看起来像整负数或浮点数的名字)的属性。这些属性按照它们添加到对象的先后顺序列出。对于在对象字面量中定义的属性,按照他们在字面量中出现的顺序列出。
  • 最后,名字为符号对象的属性按照它们添加到对象的先后顺序列出。

Object.keys

Object.prototype.fun = () => {};const str = 'ab';console.log(Object.keys(str));// ['0', '1']const arr = ['a', 'b'];console.log(Object.keys(arr));// ['0', '1']const obj = { 1: 'b', 0: 'a' };console.log(Object.keys(obj));// ['0', '1']
Copy after login

小结

用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。

Object.values

Object.prototype.fun = () => {};const str = 'ab';console.log(Object.values(str));// ['a', 'b']const arr = ['a', 'b'];console.log(Object.values(arr));// ['a', 'b']const obj = { 1: 'b', 0: 'a' };console.log(Object.values(obj));// ['a', 'b']
Copy after login

小结

用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性值组成的数组。

Object.entries

const str = 'ab';for (const [key, value] of Object.entries(str)) { console.log(`${key}: ${value}`);}// 0: a// 1: bconst arr = ['a', 'b'];for (const [key, value] of Object.entries(arr)) { console.log(`${key}: ${value}`);}// 0: a// 1: bconst obj = { 1: 'b', 0: 'a' };for (const [key, value] of Object.entries(obj)) { console.log(`${key}: ${value}`);}// 0: a// 1: b
Copy after login

小结

用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回二维数组。每一个子数组由对象的属性名、属性值组成。可以同时拿到属性名与属性值的方法。

Object.getOwnPropertyNames

Object.prototype.fun = () => {};Array.prototype.fun = () => {};const str = 'ab';console.log(Object.getOwnPropertyNames(str));// ['0', '1', 'length']const arr = ['a', 'b'];console.log(Object.getOwnPropertyNames(arr));// ['0', '1', 'length']const obj = { 1: 'b', 0: 'a' };console.log(Object.getOwnPropertyNames(obj));// ['0', '1']
Copy after login

小结

用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。

总结

我们对比了多种常用遍历的方法的差异,在了解了这些之后,我们在使用的时候需要好好思考一下,就能知道那个方法是最合适的。欢迎大家纠正补充。

更多编程相关知识,请访问:编程视频!!

The above is the detailed content of A brief discussion on several common methods of traversing arrays and objects in JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!