扩展运算符 spread
...
- 如同rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。
- 该运算符主要用于函数调用
- 如果扩展运算符后面是一个空数组 则不产生任何效果
- 由于扩展运算符可以展开数组,所以不再需要使用apply方法将数组转为函数的参数。
#例子1
# ES5 的写法
function f (x, y, z) {
...
}
let args = [0, 1, 2]
f.apply(null, args)
# ES6 的写法
f(...args)
# 例子2
# ES5 的写法
let arr1 = [0, 1, 2]
let arr2 = [3, 4, 5]
Array.prototype.push.apply(arr1, arr2)
# ES6 的写法
arr1.push(...arr2)
- 扩展运算符的应用
- 合并数组
arr1.concat(arr1, arr2) -> [...arr1, ...arr2, ...arr3]
- 与解构赋值结合
- const [first, ...rest] = [1, 2, 3, 4, 5]
- 如果将扩展运算符用于数组赋值,则只能将其放在参数的最后一位。
- 函数的返回值
- js的函数只能返回一个值 如果需要返回多个值,只能返回数组或者对象。扩展运算符提供了解决这个问题的方法。
- 通过扩展运算符可以直接将数据传入构造函数中
- 字符串
- 使用扩展运算符可以将字符串转为真正的数组
- ` [...'hello'] -> [ 'h', 'e', 'l', 'l', 'o']
- 能够正确识别32位的Unicode字符。
- 实现了iterator接口的对象
- 任何iterator接口的对象都可以用扩展运算符转为真正的数组。
- 扩展运算符内部调用的是数据结构的iterator接口,因此只要具有iterator接口的对象,都可以使用扩展运算符,如Map结构。
- Generator函数运行后会返回一个遍历器对象,因此也可以使用扩展运算符。
- 对于没有iterator接口的对象,使用扩展运算符将会报错。
- 合并数组
Array.from
- Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)对象(包括新增的数据结构Set和Map)
# 类数组对象本质特征只有一点: 即必须有length属性
let arrayLike = {
'0' : 'a',
'1' : 'b',
'2' : 'c',
length : 3
}
# ES5
let arr1 = [].slice.call(arrayLike)
# ES6
let arr2 = Array.from(arrayLike)
- 实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。Array.from都可以将其转换为真正的数组。
- 如果参数是一个真正的数组,则Array.from方法会返回一个一模一样的数组。
- 对于还没有部署该方法的浏览器 可以使用
Array.prototype.slice()
方法替代。 - Array.from还可以接收第二个参数,作用类似于数组的map方法。即对每个元素进行处理,将处理后的值放入数组。
Array.from(arrayLike, x => x * x)
# 等同于
Array.from(arrayLike).map(x => x * x)
- 还可以传入Array.from第三个参数,用来绑定this。
- Array.from可以将各种值转换为真正的数组,并且提供map功能。
- Array.from可以利用第一个参数指定第二个参数运行的次数
- ` Array.from({ length : 2 }, () => 'jack') //[ 'jack', 'jack']
- Array.from的另一个应用是将字符串转换为数组,然后返回字符串的长度,因为它能正确处理各种Unicode字符,可以避免js将大于uFFFF的Unicode字符算作两个字符的bug。
Array.of()
- Array.of方法用于将一组值转换为数组。
- 这个方法主要的目的是弥补数组构造函数Array()的不足 -> 因为参数个数的不同导致的行为的差异。
Array.of( 3 ) // [3]
Array(3) // [, , ,]
- Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载,它的行为非常统一。
- Array.of总是返回参数值组成的数组。如果没有参数,就返回一个空数组。
- Array.of方法可以用下面的代码模拟实现
function ArrayOf () {
return [].slice.call(arguments)
}
数组实例的方法
- copyWithin()
- 该方法会在当前数组内部将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。即会修改当前的数组。
Array.prototype.copyWithin(target, start = , end = this.length)
- target :从该位置开始替换数据。
- start : 从该位置开始读取疏,默认为0。如果为负值,表示倒数(相加的结果)。
- end : 到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
- 这三个参数都应该是数值,如果不是,会自动转为数值。
-
find()和findIndex()
- find
- 用于找出第一个符合条件的数组成员,
- 参数: 回调函数。
- 该方法的回调参数可以接收三个参数:依次为当前的值,当前的位置,和原数组。
- 所有数组成员依次执行该回调函数,直到找到第一个为true的成员,然后返回该成员。
- 如果没有符合的成员即返回undefined。
- findIndex
- 返回第一个符合条件的数组成员的位置。
- 如果所有数组成员都不符合,则返回-1。
- 这两个参数都可接收第二个参数,用来绑定回调函数的this值。
- 这两个方法都可以发现NaN,弥补了数组indexOf方法的不足。
- indexOf方法无法识别数组的NaNcy成员,但是findIndex方法可以借助Object.is实现。
[NaN].findIndex(y => Object.is(NaN, y)
- find
-
fill()
- 该方法使用给定值填充一个数组。
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
- fill方法用于空数组的初始化时非常方便。数组中已有的元素会被全部抹去。
- fill方法还可接收第二个和第三个参数,用于指定填充的起始位置和结束位置。
- entries() / keys() / values()
- 以上三个方法用于遍历数组。并且都返回一个遍历器对象,可用for...of循环遍历。
- keys()是对键名的遍历。
- values()是对键值的遍历。
- entries()是对键值对的遍历。
for(let index of ['a', 'b'].keys()) {
console.log(index)
}
# 如果不使用for...of循环,可以手动调用遍历器对象的next方法进行遍历。
let letter = ['a', 'b', 'c']
let entries = letter.entries()
console.log(entries.next().value) //[0. 'a']
console.log(entries.next().value) //[0. 'b']
console.log(entries.next().value) //[0. 'c']
- includes()
- 该方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。
[1, 2, 3].includes(2) // true
- 该方法的第二个参数表示搜索的起始位置。
- 如果第二个参数为负数,则表示倒数的位置。如果该负数的绝对值大于数组长度,则会重置为0开始。
- 没有该方法之前,我们通常使用数组的indexOf方法检查是否包含某个值。
- 但是indexOf方法有两个缺点
- 不够语义化
- 其含义是找到参数值的第一个出现的位置,所以要比较是否不等于-1,表达起来不够直观。
- 内部使用严格相等运算符 回导致对NaN的误判。
- 不够语义化
数组的空位
- 空位不是undefined,一个位置的值等于undefined依然是有值的。空位是没有任何值的,in运算符可以说明这一点。
- ES5对空位的处理很不一致,大多数情况下会忽略空位。
- forEach()、filter()、every()、some()都会跳过空位。
- map会跳过空位,但会保留这个值。
- join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串。
- Array.form()、 ...扩展运算符会将数组的空位转为undefined,即该方法不会忽略这个空位。
- copyWithin()会连着空位一起复制。
- fill()会将空位视为正常的数组位置。
- for...of循环也会遍历空位。
- 由于空位的处理规则非常不统一,所以建议避免出现空位。
笔记内容整理来自阮一峰老师的《ES6标准入门》