ECMAScript 6 笔记(9)- 数组的扩展

原创 乘风逐月 随笔 ES6 209阅读 2018-08-31 14:52:37 举报

阅读原文: 阮一峰:ECMAScript 6 入门

一、扩展运算符

1.含义

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

该运算符主要用于函数调用。可以与正常函数参数结合使用。

扩展运算符后面还可以放置表达式。

如果扩展运算符后面是一个空数组,则不产生任何效果。

2.扩展运算符的应用

(1)代替函数的 apply 方法
由于扩展运算符可以展开数组,所有不再需要 apply 方法,将数组转为函数的参数了。
例如:获取数组中最大的元素

上例中,ES5写法的写法,是因为JavaScript不提供求数组最大元素的函数,所以只能套用 Math.max 函数,将数组转为一个参数序列,然后求最大值。ES6的写法用扩展运算符,则可以直接使用 Math.max 方法。
(2)复制数组
数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。
扩展运算符提供了复制数组的简便写法:

(3)合并数组
扩展运算符提供了数组合并的新写法。

但是上面两种方法都是浅拷贝,使用的时候需要注意。
例如:

上例中,a3 和 a4 是用两种不同方法合并而成的新数组,但是它们的成员都是对原数组成员的引用,这就是浅拷贝。如果修改了原数组的成员,会同步反映到新数组。
(4)与解构赋值结合
扩展运算符可以与解构赋值结合起来,用于生成数组。

如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

(5)转换字符串为数组
扩展运算符还可以将字符串转为数组。

这种写法的好处是,能够正确识别四个字节的 Unicode 字符。

(6)转化实现了 Iterator 接口的对象
任何 Iterator 接口的对象。都可以用扩展运算符转化为真正的数组。

上例中,nodeList 不是一个数组,而是一个类数组的对象,使用扩展运算符可以将其转为一个真正的数组。原因在于,nodeList 对象实现了 Iterator。
对于那些没有部署 Iterator 接口的类数组对象,扩展运算符无法将其转为真正的数组。
例如:

(7)Map 和 Set 结构,Generator 函数
扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象都可以使用扩展运算符,比如 Map 结构。

Generator 函数运行后,返回一个遍历器,因此可以使用扩展运算符。

上例中, go 函数是一个 Generator 函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值转为一个数组。

二、Array.from()

Array.form 方法用于将两类对象转为真正的数组:类数组对象和可遍历的对象(包括ES6的新增数据结构 Set 和 Map )。
注: 类数组对象,必须有 length 属性。

1. 转化类数组对象

例如:

实际应用中,常见的类数组对象是操作 DOM 返回的 NodeList 集合,以及函数内部的 arguments 对象。Array.form 都可以将其转为对象。

2. 转化 Iterator 接口的数据结构

只要是部署了 Iterator 接口的数据结构,Array.from 都能将其转为数组。

上例中,字符串和 Set 结构都具有 Iterator 接口。
Array.from 可以正确处理各种 Unicode 字符。

如果参数是一个真正的数组,Array.from 会返回一个一模一样的新数组。

3.第二个参数

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

三、Array.of()

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

这个方法主要弥补数组构造函数 Array() 的不足。因为参数的个数不同,会导致 Array() 的行为有差异。

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

四、数组实例的 copyWithin()

数组实例的 copyWithin 方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。

这个方法接受三个参数:
--a. target(必需): 从该位置开始替换数据。如果为负值,表示倒数。
--b. start(可选): 从该位置开始读取数据,默认为0。如果为负值,表示倒数。
--c. end(可选): 到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
这三个参数都应该是数值,如果不是,会自动转为数值。

注: copyWithin() 方法会改变原数组,

五、数组实例的 find() 和 findIndex()

1.find()

数组实例的 find() 方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为 true 的成员,然后返回该成员。如果没有符合条件的成员,则返回 undefined 。

find 方法的回调函数可以接受三个参数,依次为:当前的值,当前的位置和元素组。

2.findIndex()

数组实例的 findIndex 方法的用法与 find 方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回 -1 。

3. 第二个参数

find() 和 findIndex() 这两个方法都接受第二个参数,用来绑定回调函数的 this 对象。

上例中,find 回调函数的 this 对象指向 person。

4. 发现 NaN

这两个方法都可以发现 NaN,弥补了数组的 indexOf 方法的不足。

六、数组实例的 fill()

fill 方法使用给定值,填充一个数组。

fill 方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。

注: 如果填充的类型是对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。

七、数组实例的 entries()、keys()、 values()

ES6 提供三个新的方法:entries()、keys()、 values(),用于遍历数组。它们都返回一个遍历器对象。可以用 for...of 循环进行遍历。
唯一的区别是: keys() 是对键名的遍历、values() 是对键值的遍历, entries() 是对键值对的遍历。

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

八、数组实例的 includes()

1.用法

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

该方法接受第二个参数,表示开始搜索的起始位置,默认值为0。如果第二个参数为负数,则表示倒数的位置。如果第二个参数大于数组长度,则会重置为从0开始。

没有这个方法之前,通常使用数组的 indexOf 方法,检查是否包含某个值。indexOf 方法有两个确定:一是不够语义化,它的含义是找到参数值的第一个出现的位置,所有要去判断是否不等于-1,表达不直观。二是,它的内部使用严格相等运算符(===)进行判断,这导致对NaN的误判。

includes 使用的是不一样的算法,没有这个问题。

2.注意问题

Set 和 Map 数据结构有一个 has 方法,需要注意与 includes 区分:
--a. Map结构的 has 方法,是用来查找键名的,比如 Map.prototype.has(key)
--b. Set 结构的 has 方法,是用来查找值的,比如 Set.prototype.has(value)

九、 数组实例的 flat()、flatMap()

在 chrome 控制台测试,这两个方法还没有实现。

1.flat()

数组的成员有时还是数组,Array.prototype.flat() 用于将嵌套的数组 “拉平”,变成一维的数组。该方法返回一个新数组,对原数组没有影响。

flat() ,默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。

如果不管有多少层嵌套,都要转成一维数组,可以用 Infinity 关键字作为参数。

如果原数组有空位,flat 方法会跳过空位。

2.flatMap()

flatMap() 方法对原数组的每一个成员执行一个函数(相当于 Array.prototype.map()),然后对返回值组成执行 flat 方法。该方法返回一个新数组,不改变原数组。

flatMap() 方法只能展开一层数组。

flatMap() 方法的参数是一个遍历函数,该函数可以接受三个参数,分别是当前数组成员、当前数组成员的位置(从0开始)、原数组。

flatMap() 方法还可以有第二个参数,用来绑定遍历函数里面的 this。

十、数组的空位

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

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

上例说明,第一个数组的0号位是有值的,第二个数组的0号位是没有值的。
ES5对空位的处理很不一致:
--a. forEach(),filter(),reduce(),every(),和 some() 都会跳过空位。
--b. map() 会跳过空位,但会保留这个值。
--c. join() 和 toString() 会将空位视为 undefined,而 undefined 和 null 会被处理成空字符串。
ES6则是明确将空位处理为 undefined。
--a. Array.from() 方法会将数组的空位,转为 undefined,即不会忽略这个空位。
--b. 扩展运算符(...),也会将空位转为 undefined。
--c. copyWthin() 会将空位一起拷贝。
--d. fill() 会将空位视为正常的数组位置。
--e. for...of 循环也会遍历空位。
--f. entries(),keys(),values(),find(),findIndex() 会将空位处理成 undefined。
由于空位的处理不统一,建议避免出现空位。

评论 ( 6 )
最新评论
乘风逐月 5F 2018-09-06 15:23:11 6F

大概 jquery vue layui mui 这些

lawrence 4F 2018-09-06 12:57:25 5F

主要用什么框架啊?

乘风逐月 3F 2018-09-06 08:45:40 4F

会用的

lawrence 2F 2018-09-05 18:38:10 3F

你用原生JS做项目么?

乘风逐月 1F 2018-09-05 17:10:41 2F

还好,现在的学习就是看书做项目。

lawrence 2018-09-05 16:35:57 1F

这么学js,是不是挺累:(