ES6学习笔记之Array

330 阅读7分钟

扩展运算符

含意

扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

console.log(...[1,2,3])
console.log(1,2,3)

const f1 = () => {
  return ['f','g']
}
let x = 1

let arr = [
  'a',
  ...['b', 'c'],                // 数组结构
  ...(x > 0 ? ['d', 'e'] : []), // 表达式
  ...f1(),                      // 函数的返回值
  ...[],                        // 空数组什么也不会做
  ]

[...{a:1}] // 报错

应用

1.替代函数的 apply 方法

es5 里面要让数组成员成为函数的参数 需要使用 apply

const sum = (...params) => {
  let total = 0
  for (let item of params) {
    total += item
  }
  return total
}
let arr = [1,2,3]

sum.apply(null, arr)

sum(...arr)

sum(1,2,3)

2.复制数组

数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。

const arr1 = [1, 2];
const arr2 = arr1;        // 复制的只是内存地址,地址的数据变了就变了。
const arr3 = [...arr1];   // 复制的地址内成员的值,在组成数组。

arr1[0] = 2;
arr2        // [2, 2]
arr3        // [1, 2]

// 还可以写成这样

const [...arr4] = arr1    // 结合了 扩展运算符和结构赋值的知识

3.合并数组

let arr1 = [1,2]
let arr2 = [2,2]

arr1.concat(arr2)

[...arr1,...arr2]

4.字符串转数组

可以正确的拆分Unicode为四个字节的字符,并正确的获取长度

[...'hello']
'hello'.split('')

// 字符Unicode 为四个字节时

[...'x\uD83D\uDE80y']
'x\uD83D\uDE80y'.split('')

'x\uD83D\uDE80y'.length       // 4
[...'x\uD83D\uDE80y'].length  // 3

将带有Iterator 接口 的对象转换成数组

可以将Map 和 Set 结构,Generator 函数等转换成数组,也可以将数组转换成另一数组。

 [...document.querySelectorAll('div')]


 let arrayLike = {
  '0': 'a',
  '1': 'b',
  length: 2
}
[...arrayLike]  //  Uncaught SyntaxError: Unexpected token ...
{...arrayLike}

就算是长得像数组的对象只要没得有 Iterator 接口,都不可通过扩展运算符转换成数值(但可以转换成对象)。

Array.from()

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map),还有字符串。

在转换数值方面与扩展运算符很相似。一下功能会达到一样的效果。

  1. 复制数组
  2. 字符串转数组
  3. 将带有Iterator 接口 的对象转换成数组

有一点比扩展字符串更好用。能将长得像数组的对象转换成真正的数组。

let arrayLike = {
  '0': 'a',
  '1': 'b',
  length: 2
}

Array.from(arrayLike)

Array.from 将长得像数组的对象转换成的数组的注意以下两点:

  1. 转换成的数值长度由length属性觉定
  2. 对象的key 值对应数值所在的位置。所以 应该是 0 <= key < length 内的整数。可以是字符串。
let obj1 = {
  '1': 'a',
  '2': 'b',
  length: 3,
}
Array.from(obj1)  // [undefined, "a", "b", ]

let obj2 = {
  'a': 'x',
  '0': 'a',
  '2': 'b',
  '1': 'c',
  length: 2,
}

Array.from(obj2)

Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。

Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]

Array.from([1, 2, 3]).map(x => x * x)
// [1, 4, 9]

Array.of()

Array.of方法用于将一组值,转换为数组。

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

构造函数也可以将参数变成数组,但是有缺点。
当构造函数有且只有一个参数且这个参数类型是数值时, 这个参数会被用来指定数组的长度。

Array()   // []
Array(3)  // [,,,]
Array(1, 2, 3) // [1, 2, 3]

Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载.

数组实例的 方法

copyWithin()

Array.prototype.copyWithin(target, start = 0, end = this.length)

修改数组将指定位置的数组成员替换成 start 到 end 之前的成员。
当start和end 为负数时表示倒数。

[0,1,2,3,4].copyWithin(0, 3, 4)     //  将3号位置覆盖到0号位置
//   [3, 1, 2, 3, 4]

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


[0,1,2,3,4,5,6].copyWithin(1, 3, 6) // 从2号位开始依次被 4到6号位的成员替换。
//  [0,3,4,5,4,5,6]

fill()

Array.prototype.fill(replace, start = 0, end = this.length)

fill方法使用给定值replace,替换掉start 到 end 之前的成员。
当start和end 为负数时表示倒数。

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

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

find()

find() 的参数为一个回调函数。
在执行时遍历数组成员,当有回调函数返回值为true时,find()返回该数组成员并停止遍历。若遍历结束都没有返回truefind() 返回undefined

主要功能用来在数组中查找符合条件的成员。

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

// -5

[1, 4, -5, 10].find((value,index,array) => {
  console.log(value,index,array)
})

上面代码中,find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。

findIndex()

findIndex() 的参数为一个回调函数。 用法与find()方法非常类似,在执行时遍历数组成员,当有回调函数返回值为true时,find()返回该数组成员的位置并停止遍历。若遍历结束都没有返回truefind() 返回-1

[1, 4, -5, 10].findIndex((value, index, arr) => value < 0)
// 2

上面代码中,findIndex方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。

返回结果跟indexOf 很相似。 都是返回第一个符合条件的数组成员的位置,若没有符合条件的成员就返回-1
但是indexOf 无法识别NaN,而findIndex 可以借助Object.is方法做到。

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

[NaN].findIndex(value => Object.is(NaN, value))   // find() 也可以
// 0

includes()

Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值。

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

includes() 判断数组内是否有NaNfindIndex 更方便。

includes() 有第二个参数,表示从该位置开始搜索。如果为负数表示倒数。

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

entries(),keys() 和 values()

let arr = ['a', 'b']

for (let index of arr.keys()) {
  console.log(index);
}
// 0
// 1

for (let item of arr.values()) {
  console.log(item);
}
// 'a'
// 'b'

for (let [index, item] of arr.entries()) {
  console.log(index, item);
}
// 0 "a"
// 1 "b"

//  如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历。

let entries = arr.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']

数组的空位

数组的空位指,数组的某一个位置没有任何值。比如,Array构造函数返回的数组都是空位。

 [, , ,]

Array(3) // [, , ,]

空位不是undefined,一个位置的值等于undefined,依然是有值的。空位是没有任何值,in运算符可以说明这一点。

let arr = [undefined, 1,  ]
0 in arr // true
1 in arr // true
2 in arr // false

Array.from 和扩展运算符 可以将数组的空位,转为undefined

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

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

copyWithin()会连空位一起拷贝。

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

fill()会将空位视为正常的数组位置。

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

for...of循环也会遍历空位。 但是map 遍历会跳过 空位.

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

arr.map(item => {
  console.log(1)
})

entries()keys()values()find()findIndex()会将空位处理成undefined

let arr = [,'a']
// entries()
[...arr.entries()] // [[0,undefined], [1,"a"]]

// keys()
[...arr.keys()] // [0,1]

// values()
[...arr.values()] // [undefined,"a"]

// find()
arr.find(x => true) // undefined

// findIndex()
arr.findIndex(x => true) // 0

1.使用 Math.max 求 arr 中最大值。

let arr = [1,2,3,9,2]

2. 求 arr2 和 arr3

const arr1 = [1]
const arr2 = arr1
const arr3 = [...arr1]

arr1[0] = 2;       

3.字符串 'a𠮷b' 拆分成数组后的长度。

let str = 'a𠮷b'
str.split('').length

[...str].length

4. obj 转换成数组的方式, 转换后的结果。

const obj = {
  a: 1,
  '0': 'xx',
  1: 'yy',
  length: 1,
}

5. 输出结果

Array.of(3)

new Array(3)

[0,1,2,3,4].copyWithin(1, -2, -1)

[0,1,2,3,4].fill('x', 1,3)


[1,3,11,2].find(value => value > 10)  
[1,3,11,2].findIndex(value => value > 10)

6. 判断一个 数组里面是否含有 NaN

// includes findIndex() find()

7. 输出结果

'aavvbbvv'.includes('aa',0)

'aavvbbvv'.includes('bb',-4)

8. 输出结果

let arr = [undefined, 1,  ]
0 in arr
1 in arr 
2 in arr