前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ES6基础 数组的扩展

ES6基础 数组的扩展

作者头像
王翔
修改2018-09-17 11:53:48
5250
修改2018-09-17 11:53:48
举报
文章被收录于专栏:王翔的专栏王翔的专栏

ECMAScript 6 入门读书小结

数组扩展

扩展运算符**...**

扩展运算符是三个点(...)。

它好比 rest 参数的逆运算很像,将一个数组转为用逗号分隔的参数序列。

代码语言:txt
复制
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>]

该运算符主要用于函数调用。

代码语言:txt
复制
function push(array, ...items) {
  array.push(...items);
}

function add(x, y) {
  return x + y;
}

const numbers = [4, 38];
add(...numbers) // 42

扩展运算符与正常的函数参数可以结合使用,非常灵活:

代码语言:txt
复制
function f(v, w, x, y, z) { }
const args = [0, 1];
f(-1, ...args, 2, ...[3]);

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

代码语言:txt
复制
const arr = [
  ...(x > 0 ? ['a'] : []),
  'b',
];

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

代码语言:txt
复制
[...[], 1]
替代ES5中函数的 apply 方法

ES6中有扩展运算符,我们不再需要apply方法将数组转换为函数参数了。

代码语言:txt
复制
// ES5 的写法
function f(x, y, z) {
  // ...
}
var args = [0, 1, 2];
f.apply(null, args); 绑定对象是null

// ES6的写法
function f(x, y, z) {
  // ...
}
let args = [0, 1, 2];
f(...args);

下面是扩展运算符取代apply方法的一个实际的例子:

代码语言:txt
复制
// ES5 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
扩展运算符运用
  • 复制数组 <font color="red">数组是引用类型,所以直接用赋值其实就是拷贝底层指针,不会克隆一个全新的数组。</font>
代码语言:txt
复制
const a1 = [1, 2];
const a2 = a1;

a2[0] = 2;
a1 // [2, 2]

所以在ES5中 克隆数组我们用concat方法:

代码语言:txt
复制
const a1 = [1, 2];
const a2 = a1.concat();

a2[0] = 2;
a1 // [1, 2]
a1会返回原数组的克隆,再修改a2就不会对a1产生影响。

在ES6中,我们可以用扩展运算符来完成:

代码语言:txt
复制
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
  • 合并数组
代码语言:txt
复制
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' ]

这两种方法都是浅拷贝,使用的时候需要注意。

代码语言:txt
复制
const a1 = [{ foo: 1 }];
const a2 = [{ bar: 2 }];

const a3 = a1.concat(a2);
const a4 = [...a1, ...a2];

a3[0] === a1[0] // true
a4[0] === a1[0] // true

也就是说,如果数组成员还是引用类型的话,这种拷贝依然是有比较大的风险的。

  • 与解构赋值结合
代码语言:txt
复制
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest  // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest  // []

const [first, ...rest] = ["foo"];
first  // "foo"
rest   // []

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

代码语言:txt
复制
const [...butLast, last] = [1, 2, 3, 4, 5];
// 报错

const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 报错
  • 实现了 Iterator 接口的对象 任何 Iterator 接口的对象,都可以用扩展运算符转为真正的数组。
代码语言:txt
复制
let nodeList = document.querySelectorAll('div');
let array = [...nodeList];

NodeList对象实现了 Iterator 。

对于那些没有部署 Iterator 接口的类似数组的对象(如普通object),扩展运算符就无法将其转为真正的数组。

  • Map 和 Set 结构,Generator 函数
代码语言:txt
复制
map的keys
let map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

let arr = [...map.keys()]; // [1, 2, 3]

Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符
const go = function*(){
  yield 1;
  yield 2;
  yield 3;
};

[...go()] // [1, 2, 3]
数组实例的 flat(),flatMap()

将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。

代码语言:txt
复制
[1, 2, [3, 4]].flat()
// [1, 2, 3, 4]

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

代码语言:txt
复制
[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]

[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]

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

代码语言:txt
复制
[1, [2, [3]]].flat(Infinity)
// [1, 2, 3]

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

代码语言:txt
复制
[1, 2, , 4, 5].flat()
// [1, 2, 4, 5]

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数组扩展
    • 替代ES5中函数的 apply 方法
      • 扩展运算符运用
        • 数组实例的 flat(),flatMap()
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档