扩展运算符可以用在函数参数,数组和对象上;
函数参数:
函数里面成为rest参数:
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
这样就不需要用arguments参数了。
a=[1,2,3,4,5]
(5) [1, 2, 3, 4, 5]
function aaa(...a){
for(let i of a){
console.log(i)
}
}
undefined
aaa(...a)
1
2
3
4
5
//该运算符将一个数组,变为参数序列
// ES5 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
注意,rest 参数之后不能再有其他参数(即只能是最后一个参数)
// 报错
function f(a, ...b, c) {
// ...
}
函数的length
属性,不包括 rest 参数。
(function(a) {}).length // 1
(function(...a) {}).length // 0
(function(a, ...b) {}).length // 1
arguments
对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call
先将其转为数组。可以for of 遍历,也可以arguments[i]获取;但是没有数组特有的方法;
rest 参数,它就是一个真正的数组,数组特有的方法都可以使用。
数组扩展运算符
console.log(1, ...[2, 3, 4], 5)
[...[], 1]
[1]
克隆数组:不是指向同一地址;
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
a1===a2 //false
合并数组
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' ]
[...'hello']
// [ "h", "e", "l", "l", "o" ]
与解构赋值结合:
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
对象的扩展运算符
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
扩展运算符的解构赋值,不能复制继承自原型对象的属性
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let { ...o3 } = o2;
o3 // { b: 2 }
o3.a // undefined
但是:
const o = Object.create({ x: 1, y: 2 });
o.z = 3;
let { x, ...newObj } = o;
let { y, z } = newObj;
x // 1
y // undefined
z // 3
变量x是单纯的解构赋值,所以可以读取对象o继承的属性;
变量y和z是扩展运算符的解构赋值,只能读取对象o自身的属性,所以变量z可以赋值成功,变量y取不到值。
{...'hello'}
// {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}
// 等同于 {...Object(true)}
{...true} // {}
// 等同于 {...Object(undefined)}
{...undefined} // {}
// 等同于 {...Object(null)}
{...null} // {}