扩展运算符

85 阅读4分钟

扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,rest是可以使用function (...arr){}的形式,将传进来东西全部接受进arr。而扩展运算符就是逆过程,将收集起来的东西再分散展开,将一个数组转为用逗号分隔的参数序列。

1.合并数组与对象

let a = [1, 2, 3];
let b = [4, 5, 6];
let c = [...a, ...b];
console.log(c) // [1,2,3,4,5,6]
const objA = {
  a:1,
  b:2
};
consto bjB = {
  c:3,
  d:4
}
console.log({
 ...objA,
 ...objB
}); //{a: 1, b: 2, c: 3, d: 4}

如果要在数组任意位置进行插入,可以用展开运算符

let arr1 = [1, 2, 3, 4];
const arr2 = ["1", "2", ...arr1, "3", "4"]
console.log(arr2); // ["1", "2", 1, 2, 3, 4, "3", "4"]

如果想要整合两个数组,并且想把某个数组放在另一个数组的任意特定位置上,要配合Math函数使用

展开运算符将数组“展开”成为不同的参数,所以任何可接收任意数量的参数的函数,都能够使用展开运算符来传参

let number = [9, 4, 7, 1];
console.log(Math.min(...number)); // 1
console.log(Math.min(number));//NAN

2.可以将数组转换为参数序列

function add(x, y) {
		return x + y;
}
const numbers = [4, 38];
add(...numbers)
console.log(add(...numbers)) // 42
console.log(add(numbers)) //4,38undefined

还可以将数组转化为逗号分隔的参数序列

const person = ['nam1', 'nam2', 'nam3', 'nam4'];
function getName() {
    console.log(arguments);
}
getName(person); // 当在调用数组时 没用扩展运算符时 得到的就是原来的函数:
getName(...person);

3.解构赋值

let a = [1, 2, 3, 4, 5, 6]
let [c, ...d] = a
console.log(c); // 1
console.log(d); // [2,3,4,5,6]]

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

const [...rest, last] = [1, 2, 3, 4, 5]; // 报错
const [first, ...rest, last] = [1, 2, 3, 4, 5]; // 报错

对象的解构赋值:明确指出的赋值名字要相对。比如const中的a和b要对应对象里面的键名,而展开运算符可以不用相对。

const {
	a,
	b,
	...data
} = {
	'a': 111,
	'b': 222,
	'c': 333,
	'd': 444
}
console.log(a); // 111
console.log(b); // 222
console.log(data); // { c: 333, d: 444 }

对象中定义一个变量a,一个变量b,在被解构的对象中进行匹配,匹配到与变量名相同的key值,就把value赋值给该变量,匹配与顺序无关,剩下的键值对以对象形式赋值给展开运算符作用的变量。

const {
    a: c,
    b,
    ...data
} = {
    'a': 111,
    'b': 222,
    'c': 333,
    'd': 444
}
// console.log(a); 
// 冒号前是用于匹配的变量名,冒号后是变量名的别名,匹配到的值最后会赋给别名,此时的a是没有值的,输出会报错。
console.log(b); // 222
console.log(c); // 111
console.log(data); // { c: 333, d: 444 }

4.数据构造

两个对象连接返回新的对象

let x = {
    name: 'autumn'
}
let y = {
    age: 18
}
let z = {
    ...x,
    ...y
}
console.log(z) //{name: 'autumn', age: 18}

两个数组连接返回新的数组

let x = ['autumn']
let y = ['wscats']
let z = [...x, ...y]
console.log(z) // ["autumn", "wscats"]

数组加上对象返回新的数组

let x = [{
    name: 'autumn'
}]
let y = {
        name: 'wscats'
}
let z = [...x, y];
console.log(z); 

数组+字符串

let x = ['autumn'];
let y = 'wscats';
let z = [...x, y];
console.log(z); //['autumn', 'wscats']  

数组+对象

let x = {
     name: ['autumn', 'wscats'],
     age: 18
}
let y = {
    ...x, //name: ['autumn','wscats'],age:18
    arr: [...x.name] //['autumn','wscats']
}
console.log(y)

5.字符串转为数组,正确识别 32 位的 Unicode 字符

console.log([...'siva']) // ['s','i','v','a']
console.log([...'x\uD83D\uDE80y'].length) // 3

6.替代apply

扩展运算符与apply一样是展开数组,可将数组转为函数的参数

function add(x, y, z) {
    console.log(x + y + z)
};
var arr = [6, 7, 8];
//ES5写法 :add.apply(null,arr); //21
//ES6写法 :         
add(...arr); //21

7.浅拷贝

数组

    var a = [1, 2, 4]
    var b = [...a]
    var c = a
    a.push(6)
    console.log(c) // [1,2,4]
    

对象

var a = {
    a: 1
}
var b = {
    ...a
}
//等价于
// let baz = Object.assign({}, a); // { a: 1 }
// a.a = 5
console.log(b.a) // 1
    

如果只是一层数组或是对象,其元素只是简单类型的元素,那么属于深拷贝(就是一层拷贝,暂时就理解为深拷贝)

let aa = {
	age: 18,
	name: 'aaa'
}

let bb = {...aa};
bb.age = 22;

console.log(aa.age); // 18

如果数组或对象中的元素是引用类型的元素,那么就是浅拷贝

let aa = {
	age: 18,
	name: 'aaa',
	address: {
		city: 'shanghai'
	}
}
let bb = {...aa};
bb.address.city = 'shenzhen';
console.log(aa.address.city);  // shenzhen

9.多维数组扁平化

var arr = [1, 2, [3, 4, [5, 6, 7]], 9, [10, 11]]

function steamroller(arr) {
    while (arr.some(item => Array.isArray(item))) {
         // arr = [].concat.apply([], arr) //es5
         arr = [].concat(...arr) //es6
    }
    return arr
}
console.log(steamroller(arr))

10.将伪数组转化为真正的数组

部署了Iterator(遍历器) 接口可以直接转数组

let nodelist = document.querySelectorAll('div')
let aa = [...nodelist]
// aa.map((item) => {
//     return console.log(item)
// })
console.log(aa) // nodelist其实是对象,转化为数组
console.log(Array.from(nodelist)) //[div, div]
console.log(nodelist)

没有部署了Iterator接口的对象不可以直接转数组

let obj = {
    name: 'zhangsan',
    age: 24,
    address: 'beijing',
}
let arr = [...obj]
console.log(arr) //不可以转数组