This is the sixth day of my participation in Gwen Challenge

preface

Arrays are one of the most commonly used data structures in development, providing a wealth of properties and methods to manipulate. This article will comb through the JS array body of all traversal, such as the article error or omission, I hope you point out the criticism, thank you!

The for loop

let arr = [1.2.3]
for(let i = 0; i < arr.length; i++){
    console.log(arr[i]) 
}
Copy the code

Here’s an example of a common for loop:

① Run let I = 0

② Determine whether I is less than arr. Length; If true, the loop ends. If false, the statement in the loop body is executed

③ after executing the loop body statement, execute i++

④ Repeat the above two steps until the cycle ends

A normal for loop iterates through the variable I to get the array members with the corresponding indices

The while loop

The while loop repeats when the result of the expression in () is converted to Boolean. When the value is true, the code in {} is executed. When the value is false, the while loop ends

let i = 0;
while (i < arr.length) {
    console.log(arr[i]);
    i++;
}
Copy the code

The for loop in

The for in loop is mostly used to iterate over objects, but it can also iterate over groups of numbers, and because it’s more common, it’s included

for (let i in arr) {
    console.log(arr[i]);
}
Copy the code

Note that the for in array is the key. For of can be directly enumerated to the value of the array

The forEach loop

arr.forEach(function(val, index, arr){
  console.log(val, index, arr);
});
Copy the code

ForEach is actually a replacement for a regular for loop, but it’s much easier to use than a for loop. You can take two arguments: the first argument represents the callback function executed each time through the loop; The second parameter indicates that this refers to the problem. The callback function takes three parameters, which respectively represent the value corresponding to the number of cycles, index of the array and arr of the original array

Note that if the callback is an arrow function, modifying this with the second argument will not succeed. Since the arrow function this is executed by default by peripheral non-arrow functions, this, call, apply, and bind cannot be modified.

let arr = [1.2.3.4];
const obj = {name:"alice"}
arr.forEach((val,index,array) = >{
    console.log(this,val,index,array);
    // The arrow function cannot change the this pointer in the arrow function with the second argument
},obj);
Copy the code

Now that you know the basics, let’s simulate the implementation _forEach:

Array.prototype._forEach = function (fn, thisTo) {
	for (let i = 0; i < this.length; i++) {
		fn.call(thisTo,this[i], i, this); }}//test code
let arr = [1.2.3.4];
const obj = {name:"alice"}
arr._forEach(function(val,index,array){
    console.log(this,val,index,array);// Normal functions can modify this reference with call
},obj);
arr._forEach((val,index,array) = >{
    console.log(this,val,index,array);// The arrow function cannot change the this pointer in the arrow function with the second argument
},obj);
Copy the code

To achieve success

Let’s look at another one that is very similar to forEach: the map loop

The map cycle

Map takes exactly the same arguments as forEach: the first argument is the callback function, the second argument is this, and the arguments in the callback function are the same.

Normally, a map needs to be accompanied by a return, which returns a new array. If there is no return, it is equivalent to forEach

So maps are often used to rearrange the data structures in arrays, using pseudo-code like this:

let arr = [
   {title:'aaaaa'.read:100.hot:true},
   {title:'bbbb'.read:100.hot:true},
   {title:'cccc'.read:100.hot:true},
   {title:'dddd'.read:100.hot:true}];let newArr = arr.map((item, index, arr) = >{
   let json={}
   json.t = ` ^_^${item.title}-- -- -- -- -- `;
   json.r = item.read+200;
   json.hot = item.hot == true && 'that's great!!!!!! ';
   return json;
});
console.log(newArr);
Copy the code

Let’s simulate and encapsulate _map again

Array.prototype._map = function(fn,thisTo){
	let res = []
	for(let i = 0; i<this.length; i++){ res[i] = fn.call(thisTo,this[i],i,this)}return res;
}
//test code
let arr = [
   {title:'aaaaa'.read:100.hot:true},
   {title:'bbbb'.read:100.hot:true},
   {title:'cccc'.read:100.hot:true},
   {title:'dddd'.read:100.hot:true}];let newArr = arr._map((item, index, arr) = >{
   let json={}
   json.t = ` ^_^${item.title}-- -- -- -- -- `;
   json.r = item.read+200;
   json.hot = item.hot == true && 'that's great!!!!!! ';
   return json;
});
console.log(newArr);
Copy the code

To achieve success

filter

The filter parameter is the same as forEach. The first parameter is the callback function, and the second parameter is this. The callback function also takes value, index, and array.

Filter is used to filter unqualified “elements” that are left behind if the callback returns true

let arr = [1.2.3.4.5.6.7.8.9.10];
let res = arr.filter(function(val,index,array){
	return val%2= =0;
})
console.log(res)/ /,4,6,8,10 [2]
Copy the code

Let’s implement _filter manually:

Array.prototype._filter = function (fn, thisTo) {
	let newArr = [];
	let key = 0;
	for (let i = 0; i < this.length; i++) {
		if (fn.call(thisTo, this[i], i, this)) {
			newArr[key] = this[i];
			key++
		}
	}
	return newArr;
}

let arr = [1.2.3.4.5.6.7.8.9.10];
let res = arr._filter(function (val, index, array) {
	return val % 2= =0;
})
console.log(res)
Copy the code

To achieve success

some

Some takes the same argument as forEach. The first argument is a callback function, and the second argument is this. The callback function takes value, index, and array.

Some is used to indicate a search, and returns true as long as an element in the array matches the criteria, false otherwise

let arr = [1.2.3.4."a"];
let res = arr.some(function(val,index,array){
	return val === "a";
});
console.log(res);//true
Copy the code

Manual encapsulation is also simpler

Array.prototype._some = function (fn, thisTo) {
  let res = false;
  for (let i = 0; i < this.length; i++) {
    if (fn.call(thisTo, this[i], i, this)) {
      res = true;
      break; }}return res;
}
//test code
let arr = [1.2.3.4."b"];
let res = arr._some(function (val, index, array) {
  return val === "a";
});
console.log(res); //false
Copy the code

To achieve success

every

This is similar to some, except that some returns true only when one element is true, whereas every returns true when all elements in the array are true, as follows:

let ints = [1.2.3.4];
let res = ints.every((val, index, array) = > {
	return typeof val === 'number';
});
console.log(res);//true
Copy the code

Emulation encapsulation _every

Array.prototype._every = function (fn, thisTo) {
  let res = true;
  for (let i = 0; i < this.length; i++) {
    if(! fn.call(thisTo,this[i], i, this)) {
      res = false;
      break; }}return res;
}
let ints = [1.1.1.1];
let res = ints._every((val, index, array) = > {
  return val == 1;
});
console.log(res) //true
Copy the code

To achieve!

The subtotal: more than five methods forEach/map/filter/some/every parameter is same, can receive two parameters, respectively is circular callback function and this point, the callback function of the parameter value value, the subscript of the corresponding array members array index and the original array

reduce

The reduce callback takes four arguments:

The first parameter: total represents the initial value, or the value returned after the last cumulative calculation

The second parameter: current value value

The third parameter: index

Fourth argument: primitive array

We can use reduce to compute the sum or hierarchy of an array, for example

let arr = [1.2.3.4.5.6.7.8.9.10];
let res = arr.reduce((total, cur, index, arr) = >{
  return total+cur;
});
 console.log(res);/ / 55
Copy the code

To see this, let’s just print out the four parameters

let arr = [1.2.3.4.5.6.7.8.9.10];
arr.reduce((total, cur, index, arr) = > {
	console.log(total, cur, index, arr);
	return total + cur;
});
Copy the code

It can be seen that each Tatal is actually the return result of the last cycle execution

Let’s simulate implementing _reduce

Array.prototype._reduce = function (fn, thisTo) {
  let total = this[0];
  for (let i = 1; i < this.length; i++) {
    total = fn.call(thisTo, total, this[i], i, this)}return total;
}
let arr = [1.2.3.4.5];
let res = arr._reduce((total, cur, index, arr) = > {
  console.log(total, cur, index, arr); // Each tatal is the result of the last iteration of the loop
  return total + cur;
});
console.log(res)
Copy the code

A successful implementation

reduceRight

ReduceRight is very similar to Reduce, except that when the callback in Reduce accumulates total, it is from left to right, while reduceRight is from right to left. Such as:

let arr = [1.2.3.4.5];
let res = arr.reduceRight((total, cur, index, arr) = > {
    console.log(total, cur, index, arr);// Each tatal is the result of the last iteration of the loop
    return total + cur;
});
console.log(res)
Copy the code

Implement _reduceRight manually

Array.prototype._reduceRight = function (fn, thisTo) { let total = this[this.length - 1]; for (let i = this.length - 1 - 1; i >= 0; i--) { total = fn.call(thisTo, total, this[i], i, this) } return total; } let arr = [1, 2, 3, 4, 5]; let res = arr._reduceRight((total, cur, index, arr) => { console.log(total, cur, index, arr); Return total + cur; return total + cur; }); console.log(res)Copy the code

A successful implementation

Now let’s look at a more special for… Of circulation

The for of circulation

for… Of applies to sets of iterator objects such as iterators/array objects/strings/maps/sets. Arrays are only used here

let arr = [1.2.3.4.5];
for (let val of arr) {
    console.log(val);/ / 1, 2, 3, 4, 5
}
Copy the code

Note: The default traversal is value

find()

Find takes a function as an argument, passes the array elements to that function, and finds the first array member that matches the criteria. If not, return undefined, as in:

let arr = [1.2.3.1.2.3]
let res = arr.find(x= >{
    return x == 2
})
console.log(res)/ / 2
Copy the code

findIndex()

Similar to find, except that findIndex looks for a location (index value) and returns -1 if it does not find one

let arr = [1.2.3.1.2.3]
let res = arr.findIndex(x= >{
    return x == 2
})
console.log(res)/ / 1
Copy the code

includes()

If an array contains an element, return true if it contains an element, false if it does not.

Includes can accept a second parameter to indicate the starting position of the search, or if the second parameter is negative, to indicate the last digit of the search

let arr = [1.2.3.1.2.3]
let res = arr.includes(1)
console.log(res)//true
Copy the code

Keys (), values(), entries()

They’re pretty much the same, so they go together. All return an iterator object, the only differences being that keys are traversal of key names, values are traversal of key values, and entries are traversal of key and value pairs. Usually used with for of, as follows:

for (let index of ['a', 'b', 'c'].keys()) { console.log(index); //0 1 2 } for (let elem of ['a', 'b', 'c'].values()) { console.log(elem); //'a', 'b', 'c' } for (let [index, elem] of ['a', 'b', 'c'].entries()) { console.log(index, elem); // 0 "a" ; 1 "b"; 2 "c" }Copy the code

flat(num/Infinity)

Flat is used to “flatten” multidimensional arrays. This method returns a new array with no effect on the original data. The parameter represents the number of nesting layers, for example:

let arr = [1.2.3[4.5[6.7]]]
let res = arr.flat(Infinity)
console.log(res)/ /,2,3,4,5,6,7 [1]
Copy the code

flatMap()

FlatMap takes a function as an argument and returns a new array where each element is the result of the callback function and the structure depth is 1. Such as:

var arr1 = [1, 2, 3, 4]; console.log(arr1.flatMap(x => [x * 2])); // [2, 4, 6, 8] console.log(arr1.flatMap(x => [[x * 2]])); [[2], [4], [6], [8]]Copy the code

END