https://www.processon.com/view/link/610a94ca1e0853337b1bd06f
1,解构赋值
1.1,解构数组
将数组中未解构的内容全部赋值合并在一个数组中给...后面的参数
function test1(){
const [a, b, ...c] = [1,5,7,12,15,18];
console.log(c); // [ 7, 12, 15, 18 ]
}
此时剩余参数必须是最后的元素,比如下面这个会报错:
function test2(){
const [a, ...b, c] = [1,5,7,12,15,18]; // 报错
console.log(c);
}
1.2,解构对象
对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
解构赋值必须是最后一个参数,否则会报错。
function test3(){
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(z); // { a: 3, b: 4 }
}
// 以下报错
let { x, ...y, z } = { x: 1, y: 2, a: 3, b: 4 };
2,取出可遍历数据
2.1,取出数组数据:将一个数组转为用逗号分隔的参数序列。
function test4() {
const arr = [...[1,5,7,12,15,18]];
console.log(arr); // [ 1, 5, 7, 12, 15, 18 ]
}
2.2,展开取出实现了迭代器的对象
2.2.1,展开字符串
扩展运算符还可以将字符串转为真正的数组。有一个重要的好处,那就是能够正确识别四个字节的 Unicode 字符。
[...'hello']
// [ "h", "e", "l", "l", "o" ]
2.2.2, 实现了 Iterator 接口的对象
任何定义了遍历器(Iterator)接口的对象,都可以用扩展运算符转为真正的数组。
let nodeList = document.querySelectorAll('div');
let array = [...nodeList];
Number.prototype[Symbol.iterator] = function*() {
let i = 0;
let num = this.valueOf();
while (i < num) {
yield i++;
}
}
console.log([...5]) // [0, 1, 2, 3, 4]
2.3,取出参数对象的所有可遍历属性,拷贝到当前对象之中
2.3.1,扩展的是普通对象
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }
// 如果扩展运算符后面是一个空对象,则没有任何效果。
{...{}, a: 1}
// { a: 1 }
如果扩展运算符后面不是对象,则会自动将其转为对象。
// 等同于 {...Object(1)}
{...1} // {}
// 等同于 {...Object(true)}
{...true} // {}
// 等同于 {...Object(undefined)}
{...undefined} // {}
// 等同于 {...Object(null)}
{...null} // {}
2.3.2,扩展的是数组:
由于数组是特殊的对象,所以对象的扩展运算符也可以用于数组。
let foo = { ...['a', 'b', 'c'] };
foo
// {0: "a", 1: "b", 2: "c"}
2.3.3,扩展运算符后面是字符串:
如果扩展运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象。
{...'hello'}
// {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}
3,函数的rest参数
3.1,rest参数:
function move(...arg) {}
3.2,将rest参数展开成参数序列(就是2.1)
function move(...args) {
fn(...args); // 这一步的...是将数组args展开成参数序列
}