es6...运算符


很多人可能看见三个点的运算符都不知道能干什么。我从最开始的不知道,到现在知道能用来展开数据,但是你知道它的具体含义和进阶用法吗

1. 基础用法

  • 展开
  • 收集
  • 类数组转化为数组
  • 增加元素或者属性
  • 合并数组/对象

官方定义 =>

Spread syntax allows an iterable, such as an array expression or string, to be expanded in places where 0 or more arguments or elements are expected or an object expression to be expanded in places where 0 or more key-value pairs (for object literals) are expected.

就是说,这个运算符可以展开为一个可迭代对象中的所有项

1.1 展开

1
2
3
4
const a = [2, 3, 4]
const b = [1, ...a, 5]

b; // [1, 2, 3, 4, 5]

1.2 收集

1
2
3
4
5
function foo(a, b, ...c) {
console.log(a, b, c)
}

foo(1, 2, 3, 4, 5); // 1, 2, [3, 4, 5]

注意,这里的运算符一定要在最后一个参数的位置或者只有它一个参数

1.3 类数组转化为数组

类数组,即和数组非常接近,都拥有一系列元素,也有length属性,也支持按下标访问,常见的如字符串,选择器返回的结果,arguments

1
2
3
4
5
6
7
8
9
const nodeList = document.getElementsByClassName("test");
const array = [...nodeList];

console.log(nodeList); //Result: HTMLCollection [ div.test, div.test ]
console.log(array); //Result: Array [ div.test, div.test ]

// 在es5时代,我们需要

var args = Array.prototype.slice.call(arguments)

1.4 增加元素或者属性

给数组新增元素

1
2
3
4
5
6
7
8
const pokemon = ['KK', 'Peter'];
const charmander = '郑伊健';

const pokedex = [...pokemon, charmander];

console.log(pokedex);

//Result: [ 'KK', 'Peter', '郑伊健' ]

给对象新增属性

1
2
3
4
5
6
7
8
9
10
const basicSquirtle = { name: 'Squirtle', type: 'Water' };
const fullSquirtle = {
...basicSquirtle,
species: 'Tiny Turtle',
evolution: 'Wartortle'
};

console.log(fullSquirtle);

//Result: { name: 'Squirtle', type: 'Water', species: 'Tiny Turtle', evolution: 'Wartortle' }

1.5 合并数组/对象

合并数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const pokemon = ['Squirtle', 'Bulbasur', 'Charmander'];
const morePokemon = ['Totodile', 'Chikorita', 'Cyndaquil'];

const pokedex = [...pokemon, ...morePokemon];

console.log(pokedex);
//Result: [ 'Squirtle', 'Bulbasur', 'Charmander', 'Totodile', 'Chikorita', 'Cyndaquil' ]

// 对象数组也一样:
const pokemon = [
{ name: 'Squirtle', type: 'Water' },
{ name: 'Bulbasur', type: 'Plant' }
];
const morePokemon = [{ name: 'Charmander', type: 'Fire' }];

const pokedex = [...pokemon, ...morePokemon];

console.log(pokedex);

//Result: [ { name: 'Squirtle', type: 'Water' }, { name: 'Bulbasur', type: 'Plant' }, { name: 'Charmander', type: 'Fire' } ]

合并对象

1
2
3
4
5
6
7
8
9
10
11
12
13
const baseSquirtle = {
name: 'Squirtle',
type: 'Water'
};

const squirtleDetails = {
species: 'Tiny Turtle Pokemon',
evolution: 'Wartortle'
};

const squirtle = { ...baseSquirtle, ...squirtleDetails };
console.log(squirtle);
//Result: { name: 'Squirtle', type: 'Water', species: 'Tiny Turtle Pokemon', evolution: 'Wartortle' }

2. 进阶

  • deepClone
  • 增加条件属性

2.1 复制一个嵌套对象

修改克隆对象的属性时,原对象属性不变。但是原对象如果有数组或者对象类型的属性,这些属性变化时,克隆对象属性改变。因为复制过来的对象是一个引用类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const pokemon = {
name: 'Squirtle',
type: 'Water',
abilities: ['Torrent', 'Rain Dish']
};

const squirtleClone = { ...pokemon };

pokemon.name = 'Charmander';
pokemon.abilities.push('Surf');

console.log(squirtleClone);

//Result: { name: 'Squirtle', type: 'Water', abilities: [ 'Torrent', 'Rain Dish', 'Surf' ]

解决方法也很简单

复制引用类型的数据/deepClone

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const pokemon = {
name: 'Squirtle',
type: 'Water',
abilities: ['Torrent', 'Rain Dish']
};

const squirtleClone = { ...pokemon, abilities: [...pokemon.abilities] };

pokemon.name = 'Charmander';
pokemon.abilities.push('Surf');

console.log(squirtleClone);

//Result: { name: 'Squirtle', type: 'Water', abilities: [ 'Torrent', 'Rain Dish' ] }

2.2 增加条件属性

实际上就是新增属性的延伸

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const pokemon = {
name: 'Squirtle',
type: 'Water'
};

const abilities = ['Torrent', 'Rain dish'];
const fullPokemon = abilities ? { ...pokemon, abilities } : pokemon;

console.log(fullPokemon);

or

const fullPokemon = {
...pokemon,
...(abilities && { abilities })
};

3. Refer

深入了解es6强大的…运算符