This is the 100th original without water. If you want to get more original good articles, please search the public and follow us~ This article was first published on the Zheng Caiyun front-end blog: 160c2d8c8d13d7 JS commonly used loop traversal, you will know several kinds of
Preface
Arrays and objects, as one of the most basic data structures, play a vital role in various programming languages. It’s hard to imagine what a programming language would look like without arrays and objects, especially JS, a weakly typed language. flexible. This article takes you to understand the usage comparison and precautions of commonly used array traversal and object traversal.
Array traversal
With the continuous development of JS, there have been more than ten traversal methods as of the ES7 specification. The following is a set 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
});
Summary
- The three are basic to traverse the array from left to right
- forEach cannot break out of the loop; for and for ..of can be skipped or interrupted using break or continue.
- for ...of directly accesses the actual elements. for traverses the array index, the forEach callback function has more abundant parameters, and the element, index, and original array 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
Summary
- Both are used to make array condition judgments, and both return a Boolean value
- Both can be interrupted
- some If an element meets the condition, it returns true and the loop is interrupted; if all elements do not meet the condition, it returns false.
- Every is the opposite of some. If the beneficial element does not meet the condition, it returns false and the loop is interrupted; if all the elements meet the condition, it returns true.
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 },
// ]
summary
- Both of them generate a new array, and neither will change the original array (not including traversing the object array, and operating the element object in the callback function)
- Both will skip empty elements. Interested students can print it out by themselves
- map will form a new array with the return value of the callback function, the length of the array is the same as the original array.
- The filter will form a new array of elements that meet the conditions of the callback function, and 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 // '底部导航';
summary
- Both are used to find array elements.
- The find method returns the value of the first element in the array that satisfies the callback function. If it does not exist, return undefined.
- findIndex It returns the index of the element found in the array, not its value, or -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 is the initial value (initialValue).
The reduceRight method is completely consistent with it except that it executes in the opposite direction (from right to left).
The callback function receives four parameters:
- accumulator: It is explained on MDN as an accumulator, but I think it is inappropriate. According to my understanding, it should be the current element. All previous array elements are processed by the callback function.
- current: the array element currently being executed.
- currentIndex: the index of the array element currently being executed.
- sourceArray: The original array, which is the array on which the reduce method is called.
If the initial value is not passed in, the reduce method will execute the callback function from index 1. If the initial value is passed in, it will start at index 0 and execute the callback cumulatively based on the initial value.
Calculate the sum of an attribute of an 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
De-duplication 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 },
// ]
Get 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 }
Reduce is very powerful, and more recommended to view this 160c2d8c8d1842 "25 advanced usages of array reduce you have to know"
Performance comparison
Having said that, what is the difference in performance of these traversal methods? Let's try it in the Chrome browser. I use each loop to execute 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
It can be seen from the printed results that the for loop is the fastest and the for of loop is the slowest
Common traversal termination, performance table comparison
Can it be terminated | ||||
---|---|---|---|---|
** | break | continue | return | performance (ms) |
for | Termination✅ | Jump out of this cycle✅ | ❌ | 2.42 |
forEach | ❌ | ❌ | ❌ | 3.12 |
map | ❌ | ❌ | ❌ | 3.74 |
for of | Termination✅ | Jump out of this cycle✅ | ❌ | 6.33 |
some | ❌ | ❌ | return true ✅ | 2.78 |
every | ❌ | ❌ | return false ✅ | 2.75 |
Finally, there will be some differences in different browser kernels, and interested students can also try it.
Object traversal
In object traversal, it is often necessary to traverse the key and value of the object. ES5 provides for...in to traverse the object. However, it involves the "enumerable properties" of object properties, prototype chain properties, etc., from the Object object below. The essence explores various methods of traversing objects, and distinguishes some characteristics of common methods.
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 过滤
summary
When using a for in loop, all the enumerable properties that can be accessed through the object are returned, including both the properties that exist in the instance and the instances that exist in the prototype. If you only need to get the instance properties of the object, you can use hasOwnProperty to filter.
When using it, use (const x in a)
instead of (x in a)
which will create a global variable.
For the loop sequence of for in, refer to [JavaScript Authoritative Guide] (Seventh Edition) 6.6.1.
- List the string attributes whose names are non-negative integers first, from smallest to largest in numerical order. This rule means that the properties of arrays and array-like objects will be enumerated in order.
- After listing all the attributes of the array-like index, list all the remaining attributes of string names (including names that look like integers or floating-point numbers). These attributes are listed in the order in which they were added to the object. The attributes defined in the object literal are listed in the order in which they appear in the literal.
- Finally, the attributes of the symbolic object are listed in the order in which they were added to the object.
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']
summary
It is used to get all enumerable property values of the object itself, but does not include the properties in the prototype, and then returns an array of property names.
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']
summary
It is used to get all enumerable property values of the object itself, but does not include the properties in the prototype, and then returns an array of property values.
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
summary
Used to get all enumerable property values of the object itself, but not including the properties in the prototype, and then return a two-dimensional array. Each sub-array is composed of the property name and property value of the object. A method to get the attribute name and attribute value at the same time.
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']
Summary
It is used to get all enumerable property values of the object itself, but does not include the properties in the prototype, and then returns an array of property names.
summary
We have compared the differences between a variety of commonly used traversal methods. After understanding these, we need to think carefully when using them to know which method is the most appropriate. Welcome everyone to correct and add.
Recommended reading
Open source works
- Front-end tabloid of Zheng Caiyun
open source address www.zoo.team/openweekly/ (WeChat exchange group on the homepage of the tabloid official website)
Recruitment
The ZooTeam front-end team (ZooTeam), a young, passionate and creative front-end team, belongs to the product R&D department of Zheng Caiyun, and the Base is located in picturesque Hangzhou. The team now has more than 40 front-end partners with an average age of 27 years old. Nearly 30% are full-stack engineers, a proper youth storm troupe. The membership consists of not only “veteran” soldiers from Ali and Netease, as well as newcomers from Zhejiang University, University of Science and Technology of China, Hangzhou Electric Power and other schools. In addition to the daily business docking, the team also conducts technical exploration and actual combat in the material system, engineering platform, building platform, performance experience, cloud application, data analysis and visualization, and promotes and implements a series of internal technical products. Explore the new boundaries of the front-end technology system.
If you want to change that you have been tossed by things, hope to start to toss things; if you want to change and have been warned, you need more ideas, but you can’t break the game; if you want to change you have the ability to make that result, but you don’t need you; if If you want to change what you want to accomplish, you need a team to support it, but there is no position for you to lead people; if you want to change the established rhythm, it will be "5 years of work time and 3 years of work experience"; if you want to change the original The comprehension is good, but there is always the ambiguity of the window paper... If you believe in the power of belief, believe that ordinary people can achieve extraordinary things, believe that you can meet a better self. If you want to participate in the process of business take-off, and personally promote the growth of a front-end team with in-depth business understanding, complete technical system, technology to create value, and influence spillover, I think we should talk. Anytime, waiting for you to write something, send it to ZooTeam@cai-inc.com
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。