Loops and traversals in JS give us a quick and easy way to do repetitive things. Learning to use different methods in different scenarios helps us write all kinds of code effectively. Here are some common methods, today let us all learn a wave of some.
for
The for loop has three expressions
- Declare loop variables
- Judgment cycle condition
- Update loop variable
Where, three expressions can be omitted, but two; But it cannot be omitted.
let arr = ['a'.'b'.'c']
for(let i = 0; i < arr.length; i++){
console.log(arr[i]) // a b c
}
Copy the code
We sometimes use a temporary variable to cache the length of the array so we don’t have to fetch it every time we go through the loop
let arr = ['a'.'b'.'c']
for(let i = 0, len = arr.length; i < len; i++){
console.log(arr[i]) // a b c
}
Copy the code
Writing this in some browsers does provide a performance boost. But in Chrome, which is based on the V8 engine, the performance is basically the same because the browser automatically optimizes it for us at the bottom. Basically, it takes statements that don’t change in the body of the loop and puts them outside the body of the loop. The pseudocode is as follows:
for(let i = 0; i < arr.length; i++){
total = a + b
arr[i] = i + total * 2
}
Copy the code
Compile and optimize the above code into the following code:
total = a + b
total2 = total * 2
n = arr.length
for(let i = 0; i < n; i++){
arr[i] = i + total2
}
Copy the code
So when you’re writing code, it’s up to you whether you want to store variables.
The for loop can loop through strings, arrays, class arrays,DOM nodes, and so on
// Walk through the class array
(function(){
for(let i=0; i<arguments.length; i++){console.log(arguments[i]) // a b
}
})('a'.'b')
Copy the code
In addition to the for loop, there are other JS loops, while loop,do-while loop, we will not say.
forEach
Does not change the original array, does not return a new array
let arr = ['a'.'b'.'c']
let arr2 = arr.forEach((item, index, arr) = > {
return item + '2'
})
console.log(arr) // ["a", "b", "c"]
console.log(arr2) // undefined
Copy the code
ForEach can also pass in a second argument to bind the this variable inside the callback function
let arr = ['a'.'b'.'c']
let arr2 = ['d'.'e'.'f']
arr.forEach(function(item, index, arr){
console.log(this[index]) // d e f
}, arr2)
Copy the code
map
It doesn’t change the original array, it returns the new array
let arr = [2.'a'.'b'.'c'.undefined.null]
let arr2 = arr.map((item, index, arr) = > {
item = item + '1'
return item + '2'
})
console.log(arr) // [2, "a", "b", "c", undefined, null]
console.log(arr2) // ["212", "a12", "b12", "c12", "undefined12", "null12"]
Copy the code
You can call it chained
let arr = [1.2.3]
let tmp = arr.map(item= > item + 1).map(item= > item + 1)
console.log(tmp) / / [3, 4, 5]
Copy the code
Map can also pass in a second parameter to bind the this variable inside the callback function
let arr = [1.2]
let arr2 = [3.4]
let tmp = arr.map(function(item, index){
return this[index]
}, arr2)
console.log(tmp) / / [3, 4]
Copy the code
filter
It doesn’t change the original array, it returns the new array
let arr = [1.2.3.4.5.6]
let tmp = arr.filter(item= > {
return item % 2= = =0
})
console.log(tmp) / / (2, 4, 6]
Copy the code
Filter can also be passed a second argument to bind the this variable inside the callback function
let arr = ['a'.'b'.'c']
let arr2 = ['aa'.'bb'.'cc']
let tmp = arr.filter(function(item, index){
return this[index] === 'bb'
}, arr2)
console.log(tmp) // ["b"]
Copy the code
There is also an operation commonly used to remove false values (undefined, null, false, 0, “, NaN, etc.) from an array
let arr = [1.undefined.2.null.3.false.0.' '.4.NaN]
let tmp = arr.filter(Boolean)
console.log(tmp) // [1, 2, 3, 4]
Copy the code
for… in
Can be used to iterate over strings, arrays, objects, etc.
let arr = ['a'.'b']
for(let key in arr){
console.log(arr[key]) // a b
}
Copy the code
Traverses the enumerable properties of an object, but does not traverse the non-enumerable properties of an object
let obj = Object.create(null, {name: {value:'zhangsan'.enumerable: true
},
// Age is not enumerable and is not used by for... In loop traversal
age:{
value:12.enumerable: false}})console.log(obj) // {name: "zhangsan", age: 12}
for(let p in obj){
console.log(p) // name
console.log(obj[p]) // zhangsan
}
Copy the code
Iterate over properties on the prototype object. What if you don’t want properties on the prototype object? Use the hasOwnProperty() method to determine filtering
class Person {
constructor(name){
this.name = name
}
}
// Gender is an attribute on the prototype object
Person.prototype.gender = 'male'
let obj = new Person('zhangsan')
for(let p in obj){
if(obj.hasOwnProperty(p)){
console.log(p) // name
}
console.log(p) // name gender
}
Copy the code
for… In also iterates over the attributes of the array itself. Due to a historical legacy, it actually iterates over the property names of the object. Arrays are also objects in which the index of each element is treated as an attribute. So when we manually add extra properties to the array, it will be iterated over.
let arr = [1.2]
arr.name = 'array1'
for(let p in arr){
console.log(arr[p]) // 1 2 array1
}
Copy the code
for… The in loop outputs the name attribute. But the length attribute is not included. The of loop fixes these problems, and let’s look at this guy from ES6.
for… of
Iterate over objects that have iterators such as strings, arrays, arrays of classes (Arguments objects,DOM NodeList objects), maps, sets, generators, etc., and can respond to break,continue, and return statements. Iterates over a Map
let arr = [['name'.'zhangsan'], ['age'.12]]
let map = new Map(arr)
for(let [key, value] of map){
console.log(key) // name age
console.log(value) // zhangsan 12
}
Copy the code
Use the continue statement to control the flow, just as you would in a for loop
let arr = [1.2.3.4.5.6]
for(let item of arr){
if(item % 2= = =0) {continue
}
console.log(item) / / 1 3 5
}
Copy the code
Now that we’re talking about for… “Of,” then it’s worth mentioning Iterator. Iterator is an interface that provides uniform access to different data structures. Let’s look at the following code first
let obj = {}
for(let item of obj){
console.log(item) // Uncaught TypeError: obj is not iterable
}
Copy the code
The code went viral, indicating that OBJ is not iterable. This is because obj does not have a built-in Iterator for… But if we want to use for… What if of iterates over an OBj object?
One method provided here is that the object’s symbol. iterator property points to the object’s default iterator method. So we just manually add a Symbol. Iterator property to the object
let obj = {}
obj[Symbol.iterator] = function* (){
yield 'a'
yield 'b'
}
for(let item of obj){
console.log(item) // a b
}
Copy the code
As you can see, the OBJ object can now be traversed, becoming more like an array. Suppose we add another line of code at the end and observe the result. Now you’re starting to feel more and more alike.
console.log([...obj]) // ["a", "b"]
Copy the code
for await… of
for await… Of creates iterative loops on an iterable and can only be used inside async function. Suppose we have an array with multiple functions executing asynchronously, and we want to execute each function synchronously
(async function fun(){
let fn1 = new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve('fn1')},1500)})let fn2 = new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve('fn2')},200)})let fnArr = [fn1, fn2]
for await (let fn of fnArr){
console.log(fn) // fn1 fn2 outputs fn1, then fn2
}
})()
Copy the code
every
The function evaluates each item in the array and returns true only if each item returns true. In layman’s terms, everyone meets the requirements.
let arr = [1.2.3]
let res = arr.every(item= > item > 0)
console.log(res) // true
Copy the code
some
If any of the items in the array returns true, the result will return true. In layman’s terms, it only takes one person to meet the requirements.
let arr = [1.2.3]
let res = arr.some(item= > item > 2)
console.log(res) // true
Copy the code
The methods every and some each take a function, which in turn takes three arguments: the current member of the array, the current index, and the entire array. This takes the same form as map,forEach,map, etc.
find
Returns the first element that matches the test criteria of the function, and stops looking for subsequent elements, or returns undefined if none matches
let arr = [1.2.3]
let res = arr.find(item= > item > 1)
console.log(res) / / 2
Copy the code
Object.keys
Keys () and Object.values() can be used to obtain the property name, property value, and key-value pair of an Object. Note that object. keys returns the property name of the Object itself and only enumerable properties
let obj = {name:'zhangsan'.age:12.job:'FE engineer'}
console.log(Object.keys(obj)) // ["name", "age", "job"]
console.log(Object.values(obj)) // ["zhangsan", 12, "FE engineer"]
console.log(Object.entries(obj)) // [["name", "zhangsan"],["age", 12],["job", "FE engineer"]]
Copy the code
Let’s look at the following code to verify this
// Attributes on prototype objects, in for... In is traversed, not found in object. keys
Object.prototype.gender = 'male'
let obj = Object.create({}, {
name: {value:'zhangsan'.enumerable:true
},
// Age is a non-enumerable attribute in for... Neither in nor object. keys
age:{
value:12.enumerable:false}})console.log(Object.keys(obj)) // ["name"]
for(let p in obj){
console.log(p) // name gender
}
Copy the code
Here you can derive a method to determine whether an object is an empty object
if(Object.keys(obj).length){
// Not an empty object
}else{
// Is an empty object
}
Copy the code
conclusion
forEach
Which is essentially a loop of arrays, andfor
Loop statements are similar, but the syntax is simpler. andforEach
Does not change the original array, does not return a new array.map
andfilter
They don’t change the original array, they return a new array. And because it returns a new array, it can be called chained. The difference ismap
Is the original array processing, one-to-one relational mapping, andfilter
Is to filter the original array and retain the array members that meet the requirements.for... in
The enumerable properties of the object are iterated over, including those on the prototype object. Designed primarily for traversing objects, not for traversing groups of numbers.for... of
Traverse hasIterator
Iterator object, avoidedfor... in
Loop all defects, and can respond correctlybreak
.continue
andreturn
Statements, etc.for await... of
Turn an asynchronous loop into a synchronous loopevery
andsome
A bit like an assertion, returning a Boolean typeObject.keys()
Returns a string array of all enumerable properties of a given object