[JS elevation] summary of common array methods in JavsScript

Review on Array

  1. ”ECMAScript array is very different from arrays in other programming languages. Like arrays in other languages, ECMAScript array is also a group of orderly data, but different from other languages, each slot in the array can store any type of data. This means that you can create an array. The first element is a string, the second element is a value, and the third element is an object. "
  2. Arrays can be created by constructor and literal. When created through a constructor, the new operator can be omitted like object creation. When created through the constructor, array elements can be passed in as parameters. But note:
    1. If only one value n is passed in, an empty array of the specified length n is created.
    2. Like objects, when you create an array using array literal notation, the Array() constructor is not called.

[expansion: some strange new things]

  1. The array length attribute is not read-only. You can delete or add elements from the end of the array by modifying the length attribute.

    let arr = [1,2,3];
    arr.length = 5;
    console.log(arr) ;//[1,2,3,empty × 2]
    console.log(arr[4]); // undefined
    
    arr.length = 1;
    console.log(arr); // [1]
    
  2. The ES6 specification redefines the empty bits in the array. If the comma value in the middle of the array [1,2,,,,, 3] is empty, its access value is undefined. However, there are differences in access values due to different methods. For example, join will treat it as an empty string.

    [1,,,,5].join('-'); // "1----5"
    

    map will skip directly:

    [1,,,,5].map(()=>6));// [6, undefined,undefined,undefined,6]
    

    Therefore, in order to avoid inconsistent behavior and consider the potential performance hazards, it is necessary to avoid using empty bit arrays. If necessary, it is explicitly filled with undefined.

  3. If you add an element to the index bit of an array that exceeds the current array length, the middle will be automatically filled with null values, and the array length will also change:

    let arr = [1,2,3]
    arr[100] = 4;
    console.log(arr);// [1, 2, 3, empty × 97, 4]
    

1. The array constructor has two static methods added in ES6 to create arrays:

  • from(): used to convert the class array structure into an array instance.

    The first parameter of Array.from() is an array like object, that is, any iteratable structure, or a structure with a length attribute and indexable elements.

  • of(): converts a set of parameters to an array instance.

1.1 Array.from()

[ES6]:Array.from() constructor is a static method, which is used to convert the class array structure into an array instance.

Example 1:

// Convert string to array
console.log(Array.from("Matt"));//["M","a","t","t"]

Example 2:

// Convert the collection and mapping to a new array
const m = new Map().set(1,2).set(3,4);
const s = new Set().add(1).add(2).add(3).add(4);

console.log(Array.from(m));// [[1,2],[3,4]]
console.log(Array.from(s));// [1,2,3,4]

Example 3:

// You can use any iteratable object
const iter = {
    *[Symbol.iterator](){
        yield 1;
        yield 2;
        yield 3;
        yield 4;
    }
}
console.log(Array.from(iter)); // [1,2,3,4]

Example 4:

// Perform a shallow copy of an existing array
const a1 = [1,2,3,4];
const a2 = Array.from(a1);

console.log(a1); //[1,2,3,4];
console.log(a1 === a2);// false

Example 5:

// You can convert the function parameter object arguments to an array
function getArgsArray(){
    return Array.from(arguments);
}
console.log(getArgsArray(1,2,3,4)); // [1, 2, 3, 4]

Example 6:

// Convert custom objects with necessary properties
const arrayLikeObject = {
    0 : 1,
    1 : 2,
    2 : 3,
    3 : 4,
    length : 4
};
console.log(Array.from(arrayLikeObject)); // [1, 2, 3, 4]

Array.from() also receives a second optional mapping function parameter. This function can directly enhance the value of the new array without creating an intermediate array like calling Array.from().map(). You can also receive a third optional parameter that specifies the value of this in the mapping function. However, this overridden this value does not apply in the arrow function.

Example:

const a1 = [1,2,3,4];
const a2 = Array.from(a1, x => x**2);
const a3 = Array.from(a1, function(x){ return x**this.exponent},{exponent:2});
console.log(a2); // [1,4,9,16]
console.log(a3); // [1,4,9,16]

1.2 Array.of()

[ES6]:Array.of() converts a set of parameters into an array instance.

Array.of() is used to replace Array.prototype.slice.call(arguments) commonly used before ES6. It is an extremely clumsy way to convert arguments objects into arrays:

console.log(Array.of(1,2,3,4)); // [1,2,3,4]
console.log(Array.of(undefined)); // [undefined]

2. Array.isArray()

  1. Determine whether it is an array: [ES6]: Array.isArray()

    The problem with using instanceof is to first assume that there is only one global execution context. If there are multiple frames in a web page, two different global execution contexts may be involved, so there will be two different versions of the Array constructor. If you want to pass an Array from one frame to another, the constructor of this Array will be different from the Array created locally in the second frame.

    The purpose of the Array.isArray() method is to determine whether a value is an array, regardless of the global execution context in which it is created.

3. Iterator method: keys(), values(),entries()

  1. [ES6]:keys(): returns the iterator of the array index,
  2. [ES6]:values(): returns the iterator of array elements,
  3. [ES6]:entries(): returns the iterator of the key/value pair
const a = ["foo", "bar", "baz", "qux"];

const aKeys = Array.from(a.keys());// [0, 1, 2, 3]
const aValues = Array.from(a.values()); // ["foo", "bar", "baz", "qux"]
const aEntries = Array.from(a.entries()); // [[0,"foo"],[1,"bar"],[2,"baz"],[3,"qux"]]

Because these methods all return iterators, their contents can be directly converted to array examples through Array.from().

In addition, using the structure of ES6, it is very easy to split key value pairs in the loop:

const a = ["foo", "bar", "baz", "qux"];
for (const [idx, element] of a.entries()){
 alert(idx);
 alert(element);
}
//0
//foo
//1
//bar
//2 
//baz
//3
//qux

4. Copy and fill method copyWith(), fill()

4.1 [ES6]:fill()

//Syntax
fill(value)
fill(value, start)
fill(value, start, end)

Used to populate the array:

let arr = new Array(10);
arr.fill("hello");

console.log(arr);
//["hello","hello","hello","hello","hello","hello","hello","hello","hello","hello",];

arr.fill("world", 5);

console.log(arr);
//["hello","hello","hello","hello","hello","world","world","world","world","world",];

arr.fill("jay", 3, 6);

console.log(arr);
//["hello","hello","hello","jay","jay","jay","world","world","world","world"]

4.2 [ES6]:copyWith()

Copies parts of the array according to the specified range, and then inserts them at the beginning of the specified index.

//Syntax
copyWithin(target)
copyWithin(target, start)
copyWithin(target, start, end)
let arr = [1, true, "hello world", { name: "jayce" }];
arr.copyWithin(0, 2);
console.log(arr, "--line3");
//
[
  "hello world",
  {
    name: "jayce",
  },
  "hello world",
  {
    name: "jayce",
  },
];
arr[0] = "JavaScript NB!";
arr[1].name = "frank";
console.log(arr, "--line16");
//
[
  "JavaScript NB!",
  {
      "name": "frank"
  },
  "hello world",
  {
      "name": "frank"
  }
]

5. Stack methods push() and pop()

Stack is a last in first out (LIFO) structure. Data items are pushed and deleted only at the top of the stack.

let colors = [];
let count = colors.push("red","green");// 2
let count1 = colors.push("yellow"); //3
let count2 = colors.pop();// "green"
let count3 = colors.pop();// "red"

Note that both push() and pop() methods have return values. The former returns the length of the array and the latter returns the deleted element itself.

6. Queue methods shift() and unshift()

Queues restrict access in the form of first in first out (FIFO, first in first out)

let list  = [1,2,3,4,5,6];
list.unshift("a","b","c"); // Return value: 9
console.log(list)
// ['a', 'b', 'c', 1, 2, 3, 4, 5, 6]
list.shift(); //'a'
list.shift(); //'b'
list.shift(); //'c'
console.log(list)
// [1, 2, 3, 4, 5, 6]

7. Sorting methods reverse() and sort()

7.1 reverse()

The reverse() method is used to reverse the array elements.

let values = ["a","b","c"];
values.reverse();
console.log(values); // ['c', 'b', 'a']
let values = [1,2,3,4,5];
values.reverse();
console.log(values);// [5,4,3,2,1]

be careful ⚠️ The reverse() method can be directly used to process String or Number arrays. If it is a String array, it will be sorted alphabetically.

7.2 sort()

The sort() method is different from reverse (). sort() calls the String() transformation function on each item. Then sort the strings in ascending order.

let values =  [0, 1, 5, 10, 15];
values.sort();
alert(values); // 0,1,10,15,5

be careful ⚠️ That is, the sort() method cannot be used directly for sorting numbers.

The sort() method can receive a comparison function to determine which value should rank first.

The comparison function receives two parameters. If the first parameter is listed in front of the second parameter, it returns a negative value; If the two parameters are equal, 0 is returned; Returns a positive value if the first parameter should come after the second.

function compare(a,b){
 return a < b ? -1 : a > b ? 1 : 0
}
let values =  [ 5, 10, 0, 1,15];
let res = values.sort(compare);
console.log(res);		// [0, 1, 5, 10, 15]
console.log(values); 	// [0, 1, 5, 10, 15]

🌟 Note: both reverse() and sort() return references to the array that called them. Therefore, in the above example, res and values are the same after execution.

values === res; // true

8. Operation method

8.1 concat() and "leveling of array parameters"

Splice one or more elements, or arrays, to the end of an array.

let color2 = ["red","green","blue"].concat("yellow",["black","brown"]);
// ["red", "green", "blue", "yellow", "black", "brown"] 

[ES6]:

By default, if the concat() method parameter contains an array, the elements of the parameter array will be taken out and added to the target array one by one. This process is called "flattening array parameters".

However, ES6 supports rewriting the default behavior, that is, it can not be flattened. The method is to specify a special symbol on the parameter array: Symbol.isConcatSpreadable, as shown in the following example:

let target = ["red","green","blue"];
let param2 = ["black","brown"];
param2[Symbol.isConcatSpreadable] = false;
let res = target.concat("yellow",param2);
console.log(res);//["red","green","blue","yellow",["black","brown"]]

In this way, the array passed in as a parameter will be added to the target array as a separate element without splitting (flattening)

Force flattening class array objects

Although for arrays, the default is to flatten, for class array objects, the default is not to flatten, but you can also explicitly set to force the flattening of class array objects.

let target =  ["red","green","blue"];
let param2 = {
    length:2,
	0: "pink",
    1: "cyan"
}
let res =  target.concat("yellow",param2);
console.log(res);//
[
    "red",
    "green",
    "blue",
    "yellow",
    {
        "0": "pink",
        "1": "cyan",
        "length": 2
    }
]

It can be seen that class array elements are not by default, so you can set it to true through the [Symbol.isConcatSpreadable] attribute to achieve forced leveling.

let target =  ["red","green","blue"];
let param2 = {
    [Symbol.isConcatSpreadable] : true,
    length:2,
	0: "pink",
    1: "cyan"
}
let res =  target.concat("yellow",param2);
console.log(res);//['red', 'green', 'blue', 'yellow', 'pink', 'cyan']

The above wording is equivalent to:

let target =  ["red","green","blue"];
let param2 = {
    length:2,
	0: "pink",
    1: "cyan"
}
param2[Symbol.isConcatSpreadable] = true;
let res =  target.concat("yellow",param2);
console.log(res);//['red', 'green', 'blue', 'yellow', 'pink', 'cyan']

8.2 more methods

8.2.1 slice() :

Used to create a new array containing one or more elements of the original array. Receive one or two parameters. If there is only one parameter, return all elements indexed to the end of the array.

A feature of the silce() method is that if there are two parameters, the returned array does not contain the element corresponding to the end index. That is, the corresponding elements of the start point index of the range will be included, and the corresponding elements of the end point index will not be included.

⚠️ Here is a very noteworthy point. If you try to use this method to copy the array, the result will be a shallow copy array.

let arr = ["hello world", 1, { name: "jayce" }];
let copy = arr.slice(0, arr.length);
arr[2].name = "frank";
console.log(arr, "--line5");//["hello world",1,{"name": "frank"}]
console.log(copy, "--line6");//["hello world",1,{"name": "frank"}]
console.log(arr === copy, "--line7");       //false
console.log(arr[0] === copy[0], "--line8"); //true
console.log(arr[1] === copy[1], "--line9"); //true
console.log(arr[2] === copy[2], "--line10");//true

Describe this process in detail.

First of all, as for strict equality, you must know that it has the following rules:

Description

The strict equality operators (=== and !==) use the Strict Equality Comparison Algorithm to compare two operands.

  • If the operands are of different types, return false.
  • If both operands are objects, return true only if they refer to the same object.
  • If both operands are null or both operands are undefined, return true.
  • If either operand is NaN, return false.
  • Otherwise, compare the two operand's values:
    • Numbers must have the same numeric values. +0 and -0 are considered to be the same value.
    • Strings must have the same characters in the same order.
    • Booleans must be both true or both false.

The most notable difference between this operator and the equality (==) operator is that if the operands are of different types, the == operator attempts to convert them to the same type before comparing.

Most importantly, if the target is a reference value type, it must be the same reference value to return true, that is, the memory addresses of the two must be the same.

For non reference value types, the literal and value types must be consistent before returning true.

In the above example, because it is a shallow copy, the third element in the array, as a reference type, will only copy its reference address. Therefore, after arr[2].name = "frank" is executed, modify the name attribute of the object in arr, and the object in copy will also change. For this reason, the return value of l--line10 is true. For Line8 and line9, it is judged that they are all equal according to the basic value type. Note that deep and shallow copies are in terms of reference types.

As for line7 returning false, why are the elements of arr and copy all congruent, but the two array objects themselves are not congruent? This is because the slice() method returns a "new array of shallow copies". Behind the slice() method, in fact, it first declares a new variable copy, and then assigns the result to the new array named copy after executing the slice() method on arr (associating the returned object to the reference address of copy)

If you want to verify it, it's easy to add / remove elements to the arr, and copy will not be affected.

8.2.2 splice() :

This is a powerful array method

Its main purpose is to insert elements in the middle of the array, but there are three different ways to use this method to achieve different effects.

  • Delete: splice(start,count), respectively pass in the starting index to be deleted and the number of elements to be deleted;

  • Insert: splice(start,0,el1,el2,...), respectively pass in and insert the starting index, delete 0 elements and the elements to be inserted

    splice(2,0,"red","green")
    
  • Replace: splice(start,n,el1,el2,...n elements) is passed in, the starting position and the number of deleted elements respectively, and then filled with the same number to achieve the purpose of replacement.

9. Search and location methods

9.1 strictly equal indexOf(), lastIndexOf(), includes()

  • indexOf(target,start): the second parameter is optional. It searches from front to back and returns the index value of the target element. If it cannot be found, it returns - 1.
  • lastIndexOf(target.start): the second parameter is optional. It searches from back to front and returns the index value of the target element. If it cannot be found, it returns - 1.
  • [ES6]: includes(): returns a Boolean value

9.2 assertion function find(), findIndex():

ECMAScript allows the array to be searched according to the defined assertion function, which is called by each index. The return value of the assertion function determines whether the elements of the corresponding index are considered to match.

The assertion function takes three parameters: the element, the index, and the array itself

  • [ES6]:find(): returns the first matching element starting from the minimum index of the array.

  • [ES6]:findIndex(): returns the index of the first matching element starting from the minimum index of the array.

    const people = [{name:'matt',age:27},{name:'Nicholas',age:29}];
    alert(people.find((element, index, array) => element.age < 28)); // {name:'matt',age:27}
    alert(people.findIndex((element, index, array) => element.age < 28)); // 0
    

10. Iterative method every(), some(), filter(), forEach(), map()

ECMAScript defines five iterative methods for the array. Each method receives two parameters: the function running with each item as the parameter, and the optional scope object as the function running context (affecting the this value in the function). The function passed to each method receives three parameters: array element, element index and array itself.

  1. every(): run the passed in function for each item of the array. If true is returned for each item, this method returns true.

  2. some(): run the passed in function for each item of the array. If one of the functions returns true, this method returns true

    let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    let everyResult = numbers.every((item, index, array) => item > 2);
    console.log(everyResult);//false
    let someResult = numbers.some((itme, index, array)=> item > 2);
    console.log(someResult);// true
    

    some() is very similar to every(), but the difference is also easy to distinguish from the literal meaning. One is that the execution of the function needs all elements to be satisfied to return true, and the other is that as long as one element is satisfied, it will return true.

  3. filter(): run the passed in function for each item of the array. The items returned by the function that return true will form an array and return.

    let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    let filterResult = numbers.filter((item, index, array) => item > 2);
    console.log(filterResult); // [3,4,5,4,3]
    
  4. forEach(): run the passed in function for each item of the array without return value.

  5. map(): run the passed in function for each item of the array. If one of the functions returns true, this method returns true.

**None of these methods change the array that calls them**

11. Merge method reduce(), reduceRight()

ECMAScript provides two merging methods for arrays: reduce(), reduceRight().
Both methods iterate over all the items of the array, and build a final return value on this basis. The reduce() method iterates from the first item of the array to the last item. reduceRight() is the opposite.

Both methods receive two parameters: the merge function that will run for each item and the optional initial value that will be used as the merge starting point. The parameter function (callback function) passed to reduce() and reduceRight() Receive four parameters: the previous merge value, the current item, the index of the current item, and the array itself. Any value returned by this function will be the first parameter of the next call to the same function. If you do not pass in an optional second parameter (as the merge starting point value) to these two methods , the first iteration will start from the second item of the array, so the first parameter passed to the merge function is the first item of the array, and the second parameter is the second item of the array.

let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array)=> prev + cur);
console.log(sum);// 15

When the merge function is executed for the first time, prev is 1 and cur is 2;
In the second execution, prev is 3 (1 + 2) and cur is 3;
...
The reduceRight() method is similar, but in the opposite direction.

let values = [1, 2, 3, 4, 5];
let sum = values.reduceRight(function(prev, cur, index, array){
    return prev + cur;
});
console.log(sum);// 15

When the merge function is executed for the first time, prev is 5 and cur is 4;
In the second execution, prev is 9 (5 + 4) and cur is 3;
...

Tags: Javascript

Posted on Fri, 03 Dec 2021 12:18:54 -0500 by DGaleDavid