Array

Constructor

Array is a native object of JavaScript and also a constructor, which can be used to generate new arrays.

var arr = new Array(2);
arr.length; // 2
arr; // [empty x 2]

In the above code, the parameter 2 of the Array() constructor means that an array of two members is generated, and each position is a null value.

If the new keyword is not used, the result is the same.

var arr = Array(2);
// Equivalent to
var arr = new Array(2);

Considering the semantics and consistency with other constructor usage, it is recommended to always add new.

The Array() constructor has a big flaw. Different numbers of parameters can lead to inconsistent behavior.

// When there are no parameters, return an empty array
new Array(); // []

// A single positive integer parameter, indicating the length of the new array returned
new Array(1); // [empty]
new Array(2); // [empty x 2]

// The value of a non-positive integer is used as a parameter and an error will be reported
new Array(3.2); // RangeError: Invalid array length
new Array(-3); // RangeError: Invalid array length

// A single non-numeric value (such as string, boolean, object, etc.) as a parameter,
// The parameter is a member of the returned new array
new Array("abc"); // ['abc']
new Array([1]); // [Array[1]]

// In the case of multiple parameters, all parameters are members of the returned new array
new Array(1, 2); // [1, 2]
new Array("a", "b", "c"); // ['a','b','c']

As you can see, the behavior of Array() as a constructor is very inconsistent. Therefore, it is not recommended to use it to generate new arrays. It is better to use array literals directly.

// bad
var arr = new Array(1, 2);

// good
var arr = [1, 2];

Note that if the parameter is a positive integer, all members of the returned array are empty. Although undefined is returned when reading, there is actually no value at that position. Although the length property can be read at this time, the key name cannot be obtained.

var a = new Array(3);
var b = [undefined, undefined, undefined];

a.length; // 3
b.length; // 3

a[0]; // undefined
b[0]; // undefined

0 in a; // false
0 in b; // true

In the above code, a is an empty array of length 3 generated by Array(), and b is an array whose three members are all undefined. These two arrays are different. When reading the key value, both a and b return undefined, but the key name of a (the serial number of the member) is empty, and the key name of b has a value.

Static method

Array.isArray()

The Array.isArray method returns a boolean value indicating whether the parameter is an array. It can make up for the shortcomings of the typeof operator.

var arr = [1, 2, 3];

typeof arr; // "object"
Array.isArray(arr); // true

In the above code, the typeof operator can only show that the type of the array is Object, and the Array.isArray method can identify arrays.

Example method

valueOf(), toString()

The valueOf method is a method owned by all objects, which means that the object is evaluated. The valueOf method of different objects is not the same, the valueOf method of the array returns the array itself.

var arr = [1, 2, 3];
arr.valueOf(); // [1, 2, 3]

The toString method is also a general method of the object, the toString method of the array returns the string form of the array.

var arr = [1, 2, 3];
arr.toString(); // "1,2,3"

var arr = [1, 2, 3, [4, 5, 6]];
arr.toString(); // "1,2,3,4,5,6"

push(), pop()

The push method is used to add one or more elements to the end of the array and returns the length of the array after adding the new element. Note that this method will change the original array.

var arr = [];

arr.push(1); // 1
arr.push("a"); // 2
arr.push(true, {}); // 4
arr; // [1,'a', true, {}]

The above code uses the push method to add four members to the array.

The pop method is used to delete the last element of the array and return that element. Note that this method will change the original array.

var arr = ["a", "b", "c"];

arr.pop(); //'c'
arr; // ['a','b']

Using the pop method on an empty array will not report an error, but return undefined.

[].pop(); // undefined

The combination of push and pop forms a "last in, first out" stack structure (stack).

var arr = [];
arr.push(1, 2);
arr.push(3);
arr.pop();
arr; // [1, 2]

In the above code, 3 is the last to enter the array, but it leaves the array first.

shift(), unshift()

The shift() method is used to delete the first element of the array and return that element. Note that this method will change the original array.

var a = ["a", "b", "c"];

a.shift(); //'a'
a; // ['b','c']

In the above code, after using the shift() method, the original array is changed.

The shift() method can traverse and clear an array.

var list = [1, 2, 3, 4];
var item;

while ((item = list.shift())) {
  console.log(item);
}

list; // []

The above code uses the list.shift() method to fetch one element at a time, thus traversing the array. Its premise is that the array element cannot be 0 or any element whose boolean value is equal to false, so such traversal is not very reliable.

The combination of push() and shift() forms a "first in, first out" queue structure (queue).

The unshift() method is used to add an element to the first position of the array and returns the length of the array after adding the new element. Note that this method will change the original array.

var a = ["a", "b", "c"];

a.unshift("x"); // 4
a; // ['x','a','b','c']

The unshift() method can accept multiple parameters, which are all added to the head of the target array.

var arr = ["c", "d"];
arr.unshift("a", "b"); // 4
arr; // ['a','b','c','d']

join()

The join() method uses the specified parameter as a separator to concatenate all array members into a string and return. If no parameters are provided, they are separated by commas by default.

var a = [1, 2, 3, 4];

a.join(""); // '1 2 3 4'
a.join(" |"); // "1 | 2 | 3 | 4"
a.join(); // "1,2,3,4"

If the array member is undefined or null or empty, it will be converted to an empty string.

[undefined, null].join('#')
//'#'

['a',,'b'].join('-')
//'a--b'

Through the call method, this method can also be used for strings or array-like objects.

Array.prototype.join.call("hello", "-");
// "hello"

var obj = { 0: "a", 1: "b", length: 2 };
Array.prototype.join.call(obj, "-");
//'ab'

concat()

The concat method is used to merge multiple arrays. It adds the members of the new array to the back of the original array members, and then returns a new array with the original array unchanged.

['hello'].concat(['world'])
// ["hello", "world"]

['hello'].concat(['world'], ['!'])
// ["hello", "world", "!"]

[].concat({a: 1}, {b: 2})
// [{ a: 1 }, {b: 2 }]

[2].concat({a: 1})
// [2, {a: 1}]

In addition to arrays as parameters, concat also accepts other types of values ​​as parameters and adds them to the end of the target array.

[1, 2, 3].concat(4, 5, 6);
// [1, 2, 3, 4, 5, 6]

If the array members include objects, the concat method returns a shallow copy of the current array. The so-called "shallow copy" refers to the reference to the object copied by the new array.

var obj = { a: 1 };
var oldArray = [obj];

var newArray = oldArray.concat();

obj.a = 2;
newArray[0].a; // 2

In the above code, the original array contains an object, and the new array generated by the concat method contains a reference to this object. Therefore, after changing the original object, the new array changes accordingly.

reverse()

The reverse method is used to reverse the array elements and return the changed array. Note that this method will change the original array.

var a = ["a", "b", "c"];

a.reverse(); // ["c", "b", "a"]
a; // ["c", "b", "a"]

slice()

The slice() method is used to extract a part of the target array and return a new array without changing the original array.

arr.slice(start, end);

Its first parameter is the starting position (starting from 0 and will be included in the returned new array), and the second parameter is the ending position (but the element itself is not included). If the second parameter is omitted, it will always return to the last member of the original array.

var a = ["a", "b", "c"];

a.slice(0); // ["a", "b", "c"]
a.slice(1); // ["b", "c"]
a.slice(1, 2); // ["b"]
a.slice(2, 6); // ["c"]
a.slice(); // ["a", "b", "c"]

In the above code, the last example slice() has no parameters, which is actually equivalent to returning a copy of the original array.

If the parameter of the slice() method is negative, it indicates the position of the reciprocal calculation.

var a = ["a", "b", "c"];
a.slice(-2); // ["b", "c"]
a.slice(-2, -1); // ["b"]

In the above code, -2 indicates the second position of the reciprocal calculation, and -1 indicates the first position of the reciprocal calculation.

If the first parameter is greater than or equal to the length of the array, or the second parameter is less than the first parameter, an empty array is returned.

var a = ["a", "b", "c"];
a.slice(4); // []
a.slice(2, 1); // []

An important application of the slice() method is to convert an array-like object into a real array.

Array.prototype.slice.call({ 0: "a", 1: "b", length: 2 });
// ['a','b']

Array.prototype.slice.call(document.querySelectorAll("div"));
Array.prototype.slice.call(arguments);

The parameters of the above code are not arrays, but by calling the slice() method on them through the call method, they can be converted into real arrays.

splice()

The splice() method is used to delete a part of the original array members, and can add new array members at the deleted position, and the return value is the deleted element. Note that this method will change the original array.

arr.splice(start, count, addElement1, addElement2, ...);

The first parameter of splice is the starting position of the deletion (starting from 0), and the second parameter is the number of elements to be deleted. If there are more parameters behind, it means that these are the new elements to be inserted into the array.

var a = ["a", "b", "c", "d", "e", "f"];
a.splice(4, 2); // ["e", "f"]
a; // ["a", "b", "c", "d"]

The above code deletes two array members from position 4 of the original array.

var a = ["a", "b", "c", "d", "e", "f"];
a.splice(4, 2, 1, 2); // ["e", "f"]
a; // ["a", "b", "c", "d", 1, 2]

In addition to deleting members, the above code also inserts two new members.

If the starting position is negative, it means deleting from the inverse position.

var a = ["a", "b", "c", "d", "e", "f"];
a.splice(-4, 2); // ["c", "d"]

The above code indicates that two members are deleted starting from the fourth position from the bottom c.

If you simply insert elements, the second parameter of the splice method can be set to 0.

var a = [1, 1, 1];

a.splice(1, 0, 2); // []
a; // [1, 2, 1, 1]

If only the first parameter is provided, it is equivalent to splitting the original array into two arrays at the specified position.

var a = [1, 2, 3, 4];
a.splice(2); // [3, 4]
a; // [1, 2]

sort()

The sort method sorts the members of the array, and the default is to sort them in lexicographic order. After sorting, the original array will be changed.

["d", "c", "b", "a"]
  .sort()
  [
    // ['a','b','c','d']

    (4, 3, 2, 1)
  ].sort()
  [
    // [1, 2, 3, 4]

    (11, 101)
  ].sort()
  [
    // [101, 11]

    (10111, 1101, 111)
  ].sort();
// [10111, 1101, 111]

The last two examples of the above code require special attention. The sort() method is not sorted by size, but lexicographically. In other words, the value will be converted into a string first, and then compared in lexicographical order, so 101 is ranked before 11.

If you want the sort method to be sorted in a custom way, you can pass in a function as a parameter.

[10111, 1101, 111].sort(function (a, b) {
  return a - b;
});
// [111, 1101, 10111]

In the above code, the parameter function of sort itself accepts two parameters, representing the two array members to be compared. If the return value of this function is greater than 0, it means that the first member is sorted after the second member; in other cases, the first element is sorted before the second element.

[
  { name: "Zhang San", age: 30 },
  { name: "李四", age: 24 },
  { name: "Wang Wu", age: 28 },
].sort(function (o1, o2) {
  return o1.age - o2.age;
});
// [
// {name: "Li Si", age: 24 },
// {name: "Wang Wu", age: 28 },
// {name: "Zhang San", age: 30}
//]

Note that the custom sort function should return a value, otherwise different browsers may have different implementations, and there is no guarantee that the results are consistent.

// bad
[1, 4, 2, 6, 0, 6, 2, 6]
  .sort((a, b) => a > b)

  [
    // good
    (1, 4, 2, 6, 0, 6, 2, 6)
  ].sort((a, b) => a - b);

In the above code, the former sorting algorithm returns a Boolean value, which is not recommended. The latter is a numerical value, which is a better way to write it.

map()

The map() method passes all the members of the array into the parameter function in turn, and then returns the result of each execution as a new array.

var numbers = [1, 2, 3];

numbers.map(function (n) {
  return n + 1;
});
// [2, 3, 4]

numbers;
// [1, 2, 3]

In the above code, all members of the numbers array execute the parameter function in turn, and the result of the operation forms a new array to return, and the original array remains unchanged.

The map() method accepts a function as a parameter. When this function is called, the map() method passes three parameters to it: the current member, the current position and the array itself.

[1, 2, 3].map(function (elem, index, arr) {
  return elem * index;
});
// [0, 2, 6]

In the above code, the callback function of the map() method has three parameters, elem is the value of the current member, index is the position of the current member, and arr is the original array ([1, 2, 3] ).

The map() method can also accept a second parameter, which is used to bind the this variable inside the callback function (see the chapter "this variable" for details).

var arr = ["a", "b", "c"];

[1, 2].map(function (e) {
  return this[e];
}, arr);
// ['b','c']

The above code uses the second parameter of the map() method to point the this object inside the callback function to the arr array.

If there is a space in the array, the callback function of the map() method will not be executed at this position, and the space in the array will be skipped.

var f = function (n) {return'a' };

[1, undefined, 2].map(f) // ["a", "a", "a"]
[1, null, 2].map(f) // ["a", "a", "a"]
[1,, 2].map(f) // ["a",, "a"]

In the above code, the map() method does not skip undefined and null, but skips the empty space.

forEach()

The forEach() method is very similar to the map() method. It also executes the parameter function sequentially on all members of the array. However, the forEach() method does not return a value and is only used to manipulate data. That is to say, if the purpose of array traversal is to get the return value, then use the map() method, otherwise use the forEach() method.

The usage of forEach() is consistent with the map() method. The parameter is a function, and the function also accepts three parameters: current value, current position, and the entire array.

function log(element, index, array) {
  console.log("[" + index + "] = " + element);
}

[2, 5, 9].forEach(log);
// [0] = 2
// [1] = 5
// [2] = 9

In the above code, forEach() traverses the array not to get the return value, but to output the content on the screen, so there is no need to use the map() method.

The forEach() method can also accept a second parameter, which binds the this variable of the parameter function.

var out = [];

[1, 2, 3].forEach(function (elem) {
  this.push(elem * elem);
}, out);

out; // [1, 4, 9]

In the above code, the empty array out is the second parameter of the forEach() method. As a result, the this keyword inside the callback function points to out.

Note that the forEach() method cannot interrupt the execution, it will always traverse all members. If you want to meet a certain condition, interrupt the traversal and use the for loop.

var arr = [1, 2, 3];

for (var i = 0; i < arr.length; i++) {
  if (arr[i] === 2) break;
  console.log(arr[i]);
}
// 1

In the above code, when the execution reaches the second member of the array, the execution will be interrupted. The forEach() method cannot do this.

The forEach() method will also skip empty spaces in the array.

var log = function (n) {
  console.log(n + 1);
};

[1, undefined, 2].forEach(log)
// 2
// NaN
// 3

[1, null, 2].forEach(log)
// 2
// 1
// 3

[1,, 2].forEach(log)
// 2
// 3

In the above code, the forEach() method does not skip undefined and null, but skips the gap.

filter()

The filter() method is used to filter array members, and the members that meet the conditions form a new array and return.

Its parameter is a function, all array members execute the function in turn, and the members whose return result is true form a new array to return. This method will not change the original array.

[1, 2, 3, 4, 5].filter(function (elem) {
  return elem > 3;
});
// [4, 5]

The above code returns array members greater than 3 as a new array.

var arr = [0, 1, "a", false];

arr.filter(Boolean);
// [1, "a"]

In the above code, the filter() method returns all members of the array arr that have a boolean value of true.

The parameter function of the filter() method can accept three parameters: the current member, the current position and the entire array.

[1, 2, 3, 4, 5].filter(function (elem, index, arr) {
  return index % 2 === 0;
});
// [1, 3, 5]

The above code returns a new array of even-numbered members.

The filter() method can also accept a second parameter, which is used to bind the this variable inside the parameter function.

var obj = { MAX: 3 };
var myFilter = function (item) {
  if (item > this.MAX) return true;
};

var arr = [2, 8, 3, 4, 1, 3, 2, 9];
arr.filter(myFilter, obj); // [8, 4, 9]

In the above code, the filter myFilter() has a this variable inside, which can be bound by the second parameter obj of the filter() method to return members greater than 3.

some(), every()

These two methods are similar to "assert" and return a Boolean value, which means to determine whether the array members meet a certain condition.

They accept a function as a parameter, and all array members execute the function in turn. This function accepts three parameters: the current member, the current position and the entire array, and then returns a Boolean value.

The some method means that as long as the return value of a member is true, the return value of the entire some method is true, otherwise it returns false.

var arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
  return elem >= 3;
});
// true

In the above code, if one member of the array arr is greater than or equal to 3, the some method returns true.

The every method is that the return value of all members is true, and the entire every method returns true, otherwise it returns false.

var arr = [1, 2, 3, 4, 5];
arr.every(function (elem, index, arr) {
  return elem >= 3;
});
// false

In the above code, not all members of the array arr are greater than or equal to 3, so false is returned.

Note that for an empty array, the some method returns false and the every method returns true, and the callback function will not be executed.

function isEven(x) {return x% 2 === 0}

[].some(isEven) // false
[].every(isEven) // true

The some and every methods can also accept a second parameter, which is used to bind the this variable inside the parameter function.

reduce(), reduceRight()

The reduce method and the reduceRight method process each member of the array in turn, and finally accumulate to a value. The difference between them is that reduce is processed from left to right (from the first member to the last member), and reduceRight is processed from right to left (from the last member to the first member), and everything else is exactly the same .

[1, 2, 3, 4, 5].reduce(function (a, b) {
  console.log(a, b);
  return a + b;
});
// 1 2
// 3 3
// 6 4
// 10 5
//Final result: 15

In the above code, the reduce method finds the sum of all members of the array. In the first execution, a is the first member 1 of the array, and b is the second member 2 of the array. In the second execution, a is the return value 3 from the previous round, and b is the third member 3. In the third execution, a is the return value 6 from the previous round, and b is the fourth member 4. In the fourth execution, a is the return value of the previous round 10, and b is the fifth member 5. At this point, all members are traversed, and the return value of the entire method is the return value 15 of the last round.

The first parameter of both the reduce method and the reduceRight method is a function. The function accepts the following four parameters.

  1. Cumulative variables, the default is the first member of the array
  2. The current variable, the default is the second member of the array
  3. Current position (starting from 0)
  4. Original array

Among these four parameters, only the first two are required, and the last two are optional.

If you want to specify an initial value for a cumulative variable, you can put it in the second parameter of the reduce method and the reduceRight method.

[1, 2, 3, 4, 5].reduce(function (a, b) {
  return a + b;
}, 10);
// 25

The above code specifies that the initial value of the parameter a is 10, so the array starts accumulating from 10, and the final result is 25. Note that at this time, b is traversed from the first member of the array.

The second parameter above is equivalent to setting a default value, which is especially useful when dealing with empty arrays.

function add(prev, cur) {
  return prev + cur;
}

[].reduce(add)
// TypeError: Reduce of empty array with no initial value
[].reduce(add, 1)
// 1

In the above code, because the empty array cannot get the initial value, the reduce method will report an error. At this time, adding a second parameter can guarantee that a value will always be returned.

The following is an example of the reduceRight method.

function subtract(prev, cur) {
  return prev - cur;
}

[3, 2, 1]
  .reduce(subtract) // 0
  [(3, 2, 1)].reduceRight(subtract); // -4

In the above code, the reduce method is equivalent to 3 minus 2 and then 1, and the reduceRight method is equivalent to 1 minus 2 and then 3.

Since these two methods will traverse the array, they can actually be used to do some traversal-related operations. For example, to find the longest array member.

function findLongest(entries) {
  return entries.reduce(function (longest, entry) {
    return entry.length > longest.length ? entry : longest;
  }, "");
}

findLongest(["aaa", "bb", "c"]); // "aaa"

In the above code, the parameter function of reduce will use the array member with the longer character length as the cumulative value. This results in traversing all members, the cumulative value is the member with the longest character length.

indexOf(), lastIndexOf()

The indexOf method returns the position of the first occurrence of the given element in the array, or -1 if it does not appear.

var a = ["a", "b", "c"];

a.indexOf("b"); // 1
a.indexOf("y"); // -1

The indexOf method can also accept a second parameter, which indicates the starting position of the search.

["a", "b", "c"].indexOf("a", 1); // -1

The code above searches for the character a from position 1, and the result is -1, which means that the search is not found.

The lastIndexOf method returns the position of the last occurrence of the given element in the array, or -1 if it does not appear.

var a = [2, 5, 9, 2];
a.lastIndexOf(2); // 3
a.lastIndexOf(7); // -1

Note that these two methods cannot be used to search for the position of NaN, that is, they cannot determine whether an array member contains NaN.

[NaN]
  .indexOf(NaN) // -1
  [NaN].lastIndexOf(NaN); // -1

This is because these two methods use the strict equality operator (===) to compare, and NaN is the only value that is not equal to itself.

Chained use

Many of the above array methods return arrays, so they can be used in chain.

var users = [
  { name: "tom", email: "tom@example.com" },
  { name: "peter", email: "peter@example.com" },
];

users
  .map(function (user) {
    return user.email;
  })
  .filter(function (email) {
    return /^t/.test(email);
  })
  .forEach(function (email) {
    console.log(email);
  });
// "tom@example.com"

In the above code, an array of all email addresses is generated first, and then the email addresses beginning with t are filtered out, and finally it is printed out.