【06】ES6: Array extension

1. Extension operator

The spread operator (spread) is three dots (…). It is the inverse operation of the rest parameter, converting an array into a comma-separated sequence of parameters.

1. Basic grammar

[...array] // array表示要转换的数组

console.log(...[1, 2, 3]) // 1 2 3
console.log(1, ...[2, 3, 4], 5) // 1 2 3 4 5
[...document.querySelectorAll('div')] // [<div>, <div>, <div>]

2. Purpose

(1) Copy array

Arrays are composite data types. If you copy them directly, you only copy the pointer to the underlying data structure instead of cloning a brand new array.

// 存在问题:a2 并不是 a1 的克隆,而是指向同一份数据的另一个指针。修改 a2,会直接导致a1 的变化。
const a1 = [1, 2]
const a2 = a1
a2[0] = 2
a1 // [2, 2]

// ES5 中用变通方法复制数组(浅拷贝)
const a1 = [1, 2]
const a2 = a1.concat()

// 使用扩展运算符复制数组(浅拷贝)
const a1 = [1, 2]
const a2 = [...a1]

(2) Merge arrays

The merged array is only a shallow copy, so you need to pay attention when using it.

const arr1 = ['a', 'b']
const arr2 = ['c']
const arr3 = ['d', 'e']

// ES5 的合并数组
arr1.concat(arr2, arr3) // [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并数组
[...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]

(3) Combined with destructuring assignment

The spread operator can be combined with destructuring assignment to generate arrays.

const arr = [1, 2, 3]
// ES5
const first = arr[0], rest = arr.slice(1)
// ES6
const [first, ...rest] = arr

console.log(first) // 输出 1
console.log(rest) // 输出 [2, 3]

If the spread operator is used for array assignment, it can only be placed at the last position of the parameter, otherwise an error will be reported.

const [...butLast, last] = [1, 2, 3, 4, 5] // 报错
const [first, ...middle, last] = [1, 2, 3, 4, 5] // 报错

(4) Convert string to array

[...'hello'] // [ "h", "e", "l", "l", "o" ]
// ES6 之前字符串转数组是通过:'hello'.split('');

(5) Convert array-like to array

// arguments
function func() {
    
    
    console.log(arguments) // [Arguments] { '0': 1, '1': 2 }
    console.log([...arguments]) [ 1, 2 ]
}
func(1, 2)

// 任何定义了遍历器(Iterator)接口的对象。都可以用扩展运算符转为真正的数组。
let nodeList = document.querySelectorAll('div')
let array = [...nodeList]

(6) Convert array to parameter array (function parameter transfer)

Convert an array into a comma-separated sequence of parameters that can be easily passed to a function.

const arr = [1, 2, 3]

function sum(a, b, c) {
    
    
	return a + b + c
}

console.log(sum(...arr)) // 输出 6

2.Array.from()

Array-like methods cannot be used directly. You need to convert the array-like array into an array first.

ES6 array’s new method Array.from(), which is used to convert array-like objects (array-like) and traversable objects (iterable) into real arrays for use (including ES6’s new data structures Set and Map).

basic grammar

Array.from(arrayLike, mapFn, thisArg)
parameter describe
arrayLike Array-like object or iterable object that you want to convert to an array
mapFn If this parameter is specified, each element in the new array will execute the callback function
thisArg Optional parameter, this object when executing callback function mapFn

arrayLike

Any object with a length property can be converted to an array through the Array.from() method.

const arrLike = {
    
    
  '0': 'a',
  '1': 'b',
  '2': 'c',
  length: 3
}

// ES5 的写法
var arr = [].slice.call(arrayLike) // ['a', 'b', 'c']
var arr = [].slice.apply(arrLike) // ['a', 'b', 'c']

// ES6 的写法
var arr = Array.from(arrLike)
// NodeList 对象
let ps = document.querySelectorAll('p')
Array.from(ps).filter(p => {
    
    
	return p.textContent.length > 100
})

// arguments 对象
function foo() {
    
    
	var args = Array.from(arguments)
	// ...
}
/* 部署了 Iterator 接口的数据结构 */
Array.from('hello') // ['h', 'e', 'l', 'l', 'o']

const namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']

const map = new Map([[1, 2], [2, 4], [4, 8]])
Array.from(map) // [[1, 2], [2, 4], [4, 8]]
// 数组对象,Array.from()会返回一个一模一样的新数组
Array.from([1, 2, 3]) // [1, 2, 3]
// 有 length 属性的对象
Array.from({
    
     length: 3 }) // [undefined, undefined, undefined]

mapFn callback function

The second parameter in Array.from is a callback function similar to the map function. The callback function will receive each item in the array as an incoming parameter, and then process the incoming value to obtain a new array. . Array.from(obj, mapFn, thisArg) can also be rewritten using map as Array.from(obj).map(mapFn, thisArg).

Array.from(arrayLike, x => x * x)
// 等同于
Array.from(arrayLike).map(x => x * x)

Array.from([1, 2, 3], x => x * x) // [1, 4, 9]
// 取出一组 DOM 节点的文本内容
let spans = document.querySelectorAll('span.name')

// map()
let names1 = Array.prototype.map.call(spans, s => s.textContent)

// Array.from()
let names2 = Array.from(spans, s => s.textContent)

thisArg

The third parameter in Array.from can bind the point of this in the callback function. This parameter is very useful. We can separate the processed data from the processing object, and encapsulate various data processing methods into In different objects, the processing method uses the same name.

When calling Array.from to convert the data object, different processing objects can be injected according to the actual situation to obtain different results, which is suitable for decoupling.

// 定义一个 obj 对象可以认作是,Array.from 回调函数中处理数据的方法集合,handle 是其中的一个方法,把 obj 作为第三个参数传给 Array.from 这样在回调函数中可以通过 this 来拿到 obj 对象。
let obj = {
    
    
  handle: function(n){
    
    
    return n + 2
  }
}

Array.from([1, 2, 3, 4, 5], function (x){
    
    
  return this.handle(x)
}, obj) // [3, 4, 5, 6, 7]

3. Array.of()

The Array.of() method is used to convert a set of values ​​into an array.

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

The main purpose of this method is to make up for the shortcomings of the array constructor Array(). Because the number of parameters is different, the behavior of Array() will be different.

Array() // []
Array(3) // [, , ,] 参数只有一个正整数时,实际上是指定数组的长度
Array(3, 11, 8) // [3, 11, 8] 返回由参数组成的新数组

In the above code, the Array() method returns different results when it has no parameters, one parameter, or three parameters. Array() will return a new array consisting of parameters only if the number of parameters is at least 2. When the parameter has only one positive integer, it actually specifies the length of the array.

Array.of() can basically be used to replace Array() or new Array(), and there are no overloads due to different parameters. Its behavior is very uniform.

Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]

Array.of() always returns an array of argument values. If there are no parameters, an empty array is returned.

The Array.of() method can be simulated with the following code.

function ArrayOf(){
    
    
	return [].slice.call(arguments)
}

4. Instance methods

1、copyWithin()

Within the current array, copies the members at the specified position to other positions (the original members will be overwritten), and then returns the current array. This method will change the original array.

Array.prototype.copyWithin(target, start = 0, end = this.length)
parameter describe
target Required parameters. Start replacing data from this position. If it is a negative value, it represents the reciprocal
start Optional parameters. Start reading data from this position, which defaults to 0. If it is a negative value, it means counting from the end.
end Optional parameters. Stop reading data at this position, which is equal to the array length by default. If it is a negative value, it means counting from the end.

These three parameters should all be numerical values. If not, they will be automatically converted to numerical values.

// 将3号位直到数组结束的成员(4和5),复制到从0号位开始的位置,覆盖原来的1和2。
[1, 2, 3, 4, 5].copyWithin(0, 3) // [4, 5, 3, 4, 5]

// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4) // [4, 2, 3, 4, 5]

// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1) // [4, 2, 3, 4, 5]

2、find()、findIndex()、findLast()、findLastIndex()

The array retrieval method will not change the original array.

method illustrate
find() Used to find the first array member that meets the criteria. Returns the member if there is one, or undefined if there is no member that meets the criteria.
findIndex() Returns the position of the first array member that meets the criteria, or -1 if none of the members meet the criteria.
findLast() Used to find the first array member that meets the criteria. Returns the member if there is one, or undefined if there is no member that meets the criteria. Starting from the last member of the array, check forward.
findLastIndex() Returns the position of the first array member that meets the criteria, or -1 if none of the members meet the criteria. Starting from the last member of the array, check forward.

The first parameter is a callback function, which is executed by all array members in sequence.

The second parameter is the this object used to bind the callback function.

[1, 4, -5, 10].find(n => n < 0) // -5

// 回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。
[1, 5, 10, 15].find(function(value, index, arr) {
    
    
	return value > 9
}) // 10

[1, 5, 10, 15].findIndex(function(value, index, arr) {
    
    
	return value > 9
}) // 2

// 绑定回调函数的this对象。
function f(v){
    
    
	return v > this.age
}
let person = {
    
    name: 'John', age: 20}
[10, 12, 26, 15].find(f, person) // 26
const array = [
	{
    
     value: 1 },
	{
    
     value: 2 },
	{
    
     value: 3 },
	{
    
     value: 4 }
]

array.findLast(n => n.value % 2 === 1) // { value: 3 }
array.findLastIndex(n => n.value % 2 === 1) // 2

These four methods can all find NaN, making up for the shortcomings of the indexOf() method of the array.

array.indexOf(item, start = 0) . Returns the position of a specified element in the array, or -1 if the specified element is not found in the array.

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

// 借助 Object.is() 方法
[NaN].findIndex(y => Object.is(NaN, y)) // 0

3、filter()

Filter the array members and return the members that meet the conditions into a new array. This method does not change the original array.

The first parameter is a callback function. All array members execute the callback function in sequence, and the members whose return result is true form a new array and return it.

The second parameter is the this object used to bind the callback function.

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

[0, 1, 'a', false].filter(Boolean) // [1, 'a']
// 回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。
[1, 2, 3, 4, 5].filter(function (elem, index, arr) {
    
    
	return index % 2 === 0
}) // [1, 3, 5]

// 绑定回调函数内部的this变量。
const obj = {
    
     MAX: 3 }
const myFilter = function (item) {
    
    
	if (item > this.MAX) return true
}
[2, 8, 3, 4, 1, 3, 2, 9].filter(myFilter, obj) // [8, 4, 9]

4、map()

Pass all members of the array into the parameter function in turn, and then return the results of each execution into a new array. The original array will not be changed.

The first parameter is a callback function. All array members execute the callback function in sequence, and the results form a new array and are returned.

The second parameter is the this object used to bind the callback function.

[1, 2, 3].map(function (n) {
    
    
	return n + 1
}) // [2, 3, 4]
// 回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。
[1, 2, 3].map(function(elem, index, arr) {
    
    
	return elem * index
}) // [0, 2, 6]


// 绑定回调函数内部的this变量。
const arr = ['a', 'b', 'c']
[1, 2].map(function (e) {
    
    
	return this[e]
}, arr) // ['b', 'c']

5、forEach()

Array loop. Called for each element of the array, passing the element to the callback function. No result is returned, the return value is undefined. Modifying array elements will change the original array.

The first parameter is a callback function, and all array members execute the callback function in sequence, looping through it.

The second parameter is the this object used to bind the callback function.

// 回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。
const arr = ['a', 'b', 'c']

arr.forEach(function(currentValue, index, arr) {
    
    
	console.log(currentValue)
})
// 'a' 0 ['a', 'b', 'c']
// 'b' 1 ['a', 'b', 'c']
// 'c' 2 ['a', 'b', 'c']

Interrupt loop

(1) Use for loop or for in loop instead. break ends the entire loop, continue exits this loop.

let list = [1, 2, 3, 4]
for (let i = 0; i < list.length; i++) {
    
    
	if (i == 1) {
    
    
		continue // 退出本次循环
	}
	if (i == 2) {
    
    
		break // 结束整个循环
	}
}
// break 只会结束最里层的 for 循环,继续外面的 for 循环
for (var i = 1; i < 4; i++) {
    
    
	for(var j = 1; j < 6; j++) {
    
    
		console.log(i * j)
		if(j > 2) break
	}
} // 1 2 3 2 4 6 3 6 9
for 循环中 return 语句:跳出 for 循环,且不执行 for 循环之外的语句,直接跳出当前函数,返回 return 后的值。

因为 js 中 for 是没有局部作用域的概念的,所以只有把 for 循环放在函数中时,才可以在for循环中使用 return 语句。

(2) Return, break, and continue cannot terminate the forEach loop. Return in forEach is equivalent to continue in the for loop and can exit this loop.

// return 3 的元素跳过
var arr = [1, 2, 3, 4, 5]

arr.forEach(function (item) {
    
    
    if (item === 3) {
    
    
        return
    }
    console.log(item)
})
// 1
// 2
// 4
// 5

(3) Use try...catch, throw to throw an exception, and terminate the forEach loop.

try {
    
    
	[1, 2, 3].forEach(item => {
    
    
		if (item === 2) throw('哈哈哈')
		console.log(item)
	})
} catch(e) {
    
    
	console.log(e, 'e')
}

// 1
// '哈哈哈' e

(4) Implemented through some and every. every terminates the loop when it encounters return false. some terminates the loop when it encounters return true.

// 使用 Array.some()
arr.some(item => {
    
    
	console.log(item) 
	return item === 2 // 当有数组有一项满足条件时结束并返回 true
})
 
// 使用 Array.ervey()
arr.every(item => {
    
    
	console.log(item)
	return item !== 2 // 检查数字中是否每一项都满足条件,如果有一项不满足就结束循环并返回 false
})

6、some()、every()

These two methods are similar to "assert" and return a Boolean value to determine whether the array members meet certain conditions. The original array will not be changed.

The first parameter is a callback function, which is executed by all array members in sequence. This function accepts three parameters: the current member, the current position and the entire array, and then returns a Boolean value.

The second parameter is the this object used to bind the callback function.

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

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

arr.some() will return true as long as one item meets the condition, otherwise it will return false; arr.every() will return true only if all items meet the condition, otherwise it will return false.

7、reduce()

reduce() accepts a function as an accumulator and reduces the array starting from the first value until the last value is reduced. Finally calculated as a value. The original array will not be changed.

parameter illustrate
(prev, cur, index, arr) => {} Required, callback function.
prev: required. The initial value initialValue, or the return value after the calculation is completed.
cur: required. arr The current accumulated item of the array.
index: optional. The index of the current accumulated item.
arr: optional. The non-empty array of arr to be accumulated.
initialValue Optional, initial value. When there is no initial value, the prev accumulated for the first time by the callback function is the first item of arr, cur is the second item of arr, and the value of index is 1.
[1, 2, 3, 4, 5].reduce(function (a, b) {
    
    
	console.log(a, b) // 1 2 | 3 3 | 6 4 | 10 5 
	return a + b
}) // 15

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

8、fill()

arr.fill(value, start = 0, end = arr.length) fills all elements in an array from the start index to the end index with a fixed value. Excludes terminating index. Starting index, default value is 0. Terminating index, default value is this.length.

['a', 'b', 'c'].fill(7) // [7, 7, 7]

new Array(3).fill(7) // [7, 7, 7]

['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7, 'c']

Note that if the filled type is an object, the object assigned is the same memory address, not the deep copy object.

let arr = new Array(3).fill({
    
    name: 'Mike'})
arr[0].name = 'Ben'
arr // [{name: 'Ben'}, {name: 'Ben'}, {name: 'Ben'}]

let arr = new Array(3).fill([])
arr[0].push(5)
arr // [[5], [5], [5]]

9、entries()、keys() 和 values()

Used to traverse the array. They both return a traverser object, which can be traversed using a for...of loop. The only difference is that keys() traverses key names, values() traverses key values, and entries() traverses key-value pairs. Traverse.

for (let index of ['a', 'b'].keys()) {
    
    
	console.log(index)
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
    
    
  console.log(elem)
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
    
    
  console.log(index, elem)
}
// 0 'a'
// 1 'b'

10、includes()

The Array.prototype.includes method returns a Boolean value indicating whether an array contains a given value, similar to the string's includes method.

[1, 2, 3].includes(2)	// true
[1, 2, 3].includes(4) // false
[1, 2, NaN].includes(NaN) // true

The second parameter of this method indicates the starting position of the search, which defaults to 0. If the second parameter is a negative number, it represents the reciprocal position. If it is greater than the array length (for example, the second parameter is -4, but the array length is 3), it will be reset to start from 0.

[1, 2, 3].includes(3, 3) // false
[1, 2, 3].includes(3, -1) // true

Before this method existed, we usually used the indexOf method of the array to check whether it contains a certain value.

The indexOf method has two disadvantages:

First, it is not semantic enough. Its meaning is to find the first occurrence position of the parameter value, so it is necessary to compare whether it is not equal to -1, which is not intuitive enough to express.

Second, it uses the strict equality operator (===) internally for judgment, which can lead to misjudgment of NaN. includes uses a different judgment algorithm, so there is no such problem.

if (arr.indexOf(el) !== -1) {
    
    
	// ...
}

[NaN].indexOf(NaN) // -1
[NaN].includes(NaN) // true

11、flat()、flatMap()

Array.prototype.flat()

Used to "flatten" nested arrays into one-dimensional arrays. This method returns a new array and does not change the original array.

flat() will only "flatten" one layer by default. If you want to "flatten" a multi-layer nested array, you can write the parameter of the flat() method as an integer, indicating the number of layers you want to flatten. The default is 1. When the parameter value is Infinity, no matter how many levels of nesting there are, it will be converted into a one-dimensional array.

[1, 2, [3, 4]].flat() // [1, 2, 3, 4] 拉平一层

[1, 2, [3, [4, 5]]].flat() // [1, 2, 3, [4, 5]] 拉平一层

[1, 2, [3, [4, 5]]].flat(2) // [1, 2, 3, 4, 5] 拉平两层

[1, [2, [3]]].flat(Infinity) // [1, 2, 3] 全部拉平

[1, 2, , 4, 5].flat() // [1, 2, 4, 5] 跳过空位

Array.prototype.flatMap()

Execute a function on each member of the original array (equivalent to executing Array.prototype.map() ), and then execute the flat() method on the array of returned values. This method returns a new array without changing the original array.

flatMap() can only expand one level of array.

The first parameter is a traversal function, which can accept three parameters, namely the current array member, the position of the current array member (starting from zero), and the original array.

The second parameter is used to bind this in the traversal function.

// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
[2, 3, 4].flatMap((x) => [x, x * 2]) // [2, 4, 3, 6, 4, 8]

// 相当于 [[[2]], [[4]], [[6]], [[8]]].flat()
[1, 2, 3, 4].flatMap(x => [[x * 2]]) // [[2], [4], [6], [8]]

arr.flatMap(function callback(currentValue[, index[, array]]) {
    
    
	// ...
}[, thisArg])

12、at()

For a long time, JavaScript has not supported negative indexing of arrays. If you want to refer to the last member of an array, you cannot write arr[-1], you can only use arr[arr.length - 1].

This is because the square bracket operator [] is used not only for arrays but also for objects in the JavaScript language. For objects, the key name is inside the square brackets. For example, obj[1] refers to the key with the key name string 1. Similarly, obj[-1] refers to the key with the key name string-1. Since JavaScript arrays are special objects, negative numbers inside square brackets have no other semantics. That is to say, it is impossible to add new syntax to support negative indexes.

To solve this problem, ES2022 adds the at() method to array instances, which accepts an integer as a parameter, returns the member at the corresponding position, and supports negative indexing. This method can be used not only for arrays, but also for strings and typed arrays (TypedArray).

const arr = [5, 12, 8, 130, 44]
arr.at(2) // 8
arr.at(-2) // 130

// 如果参数位置超出了数组范围,at()返回undefined。
const sentence = 'This is a sample sentence';
sentence.at(0) // 'T'
sentence.at(-1) // 'e'
sentence.at(-100) // undefined
sentence.at(100) // undefined

13、toReversed()、toSorted()、toSpliced()、with()

Many traditional methods of arrays will change the original array, such as push(), pop(), unshift(), shift(), etc. As long as these methods are called on the array, its value changes. There is now a proposal that allows operations on arrays to return a copy of the original array without changing it.

There are four such methods in total.

  • Array.prototype.toReversed() -> Array
  • Array.prototype.toSorted(compareFn) -> Array
  • Array.prototype.toSpliced(start, deleteCount, ...items) -> Array
  • Array.prototype.with(index, value) -> Array

They respectively correspond to the original methods of the array.

The original methods corresponding to these four new methods have exactly the same meaning and usage. The only difference is that the original array will not be changed, but a copy of the original array will be returned after the operation.

  • toReversed() 对应 reverse(),用来颠倒数组成员的位置。
  • toSorted() 对应 sort(),用来对数组成员排序。
  • toSpliced() 对应 splice(),用来在指定位置,删除指定数量的成员,并插入新成员。
  • with(index, value) 对应 splice(index, 1, value),用来将指定位置的成员替换为新的值。
const sequence = [1, 2, 3]
sequence.toReversed() // [3, 2, 1]
sequence // [1, 2, 3]

const outOfOrder = [3, 1, 2]
outOfOrder.toSorted() // [1, 2, 3]
outOfOrder // [3, 1, 2]

const array = [1, 2, 3, 4]
array.toSpliced(1, 2, 5, 6, 7) // [1, 5, 6, 7, 4]
array // [1, 2, 3, 4]

const correctionNeeded = [1, 1, 3]
correctionNeeded.with(1, 2) // [1, 2, 3]
correctionNeeded // [1, 1, 3]

14、isArray()

Determine the JS object, if the value is an Array, it is true, otherwise it is false.

Array.isArray(obj)
// 下面的函数调用都返回 true
Array.isArray([])
Array.isArray([10])
Array.isArray(new Array())
Array.isArray(new Array('a', 'b', 'c'))
// 鲜为人知的事实:其实 Array.prototype 也是一个数组。
Array.isArray(Array.prototype)

// 下面的函数调用都返回 false
Array.isArray()
Array.isArray({
    
    })
Array.isArray(null)
Array.isArray(undefined)
Array.isArray(17)
Array.isArray('Array')
Array.isArray(true)
Array.isArray(false)
Array.isArray(new Uint8Array(32))
Array.isArray({
    
     __proto__: Array.prototype })

How to determine arrays in ES5

(1) typeof type detection

There is no problem with judging basic types, but when judging an array, object is returned. (string, number, undefined, boolean, symbol, object, function)

// 基本类型
typeof 123 // number
typeof '123' // string
typeof true // boolean

// 引用类型
typeof [1, 2, 3] // object

(2) Judgment by instanceof

The instanceof operator is used to determine whether the current object is an instance of a constructor.

var arr = ['a', 'b', 'c']
console.log(arr instanceof Array) // true 
console.log(arr.constructor === Array) // true

Insert image description here
The prototype chain of the array instance points to the Array.prototype property. The instanceof operator is used to detect whether the Array.prototype property exists on the array's prototype chain. The arr variable in the above code is an array, and everything has the Array.prototype property. The return value is true, which makes it easy to determine the array type.

However, it should be noted that the prototype attribute can be modified, so it does not necessarily mean that it will always be true if it is initially judged to be true.

(3) Judgment by constructor

constructor is an attribute on the prototype object of the constructor, pointing to the current constructor.

The prototype object on the instance object produced by new has the constructor attribute pointing to the constructor Array, from which we can determine the type of an array.

var arr = new Array('a', 'b', 'c')
arr.constructor === Array //true

Insert image description here
The constructor can be overridden, so it is not guaranteed to be an array. (Common prototypal inheritance)

var str = 'abc'
str.constructor = Array
str.constructor === Array // true

(4)Object.prototype.toString

The toString method of the object returns [object type], where type is the current data type.

 Object.prototype.toString.call(arr) === '[object Array]'

5. Gaps in the array

An empty position in an array means that there is no value in a certain position of the array.

The empty position is not undefined. If the value of a certain position is equal to undefined, it still has value. Empty positions have no value.

由于空位的处理规则非常不统一,所以建议避免出现空位。

forEach(), filter(), reduce(), every() and some() all skip gaps.

map() will skip gaps but keep the value

join() and toString() treat gaps as undefined, and undefined and null are treated as empty strings.

// forEach 方法
[, 'a'].forEach((x, i) => console.log(i)) // 1

// filter 方法
['a', , 'b'].filter(x => true) // ['a', 'b']

// every 方法
[, 'a'].every(x => x === 'a') // true

// reduce 方法
[1, , 2].reduce((x, y) => x + y) // 3

// some 方法
[, 'a'].some(x => x !== 'a') // false

// map 方法
[, 'a'].map(x => 1) // [, 1]

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

// toString 方法
[, 'a', undefined, null].toString() // ',a,,'

The Array.from() method will convert the empty bits in the array to undefined, that is to say, this method will not ignore the empty bits.

Array.from(['a', , 'b']) // ['a', undefined, 'b']

The spread operator (…) also converts empty bits to undefined.

[...['a', , 'b']] // ['a', undefined, 'b']

copyWithin() will copy the empty spaces together.

[, 'a', 'b', ,].copyWithin(2, 0) // [, 'a', , 'a']

fill() treats gaps as normal array positions.

new Array(3).fill('a') // ['a', 'a', 'a']

The for…of loop will also iterate through the gaps.

let arr = [, ,]
for (let i of arr) {
    
    
	console.log(1)
}
// 1
// 1

entries(), keys(), values(), find(), and findIndex() will treat gaps as undefined.

// entries()
[...[, 'a'].entries()] // [[0, undefined], [1, 'a']]

// keys()
[...[, 'a'].keys()] // [0, 1]

// values()
[...[, 'a'].values()] // [undefined, 'a']

// find()
[, 'a'].find(x => true) // undefined

// findIndex()
[, 'a'].findIndex(x => true) // 0

Guess you like

Origin blog.csdn.net/weixin_45559449/article/details/134605069