…运算符的作用
简化书写长度,提升开发效率
…运算符分类:读和写,ES6和ES7
- 读的场景
var arg = [1,2,3]; console.log(…arg); -展开作用 - 写的场景
function test (…arg){}; test(1,2,3);-收集作用 - ES6
主要作用在数组上 - ES7
主要作用在对象上
ES6中写的场景
我们先来看一个求平均分的案例(需要去掉最高分和最低分)
此处我们是使用的是ES5中的常规写法
function average(){
var averageNumber = 0;
//将arguments转化为数组
var arr = [].slice.call(arguments);
//数组按照从小到大排序
arr.sort(function(a, b){
return a - b;
});
arr.pop();
arr.shift();
for(var i = 0; i < arr.length; i++){
averageNumber += arr[i];
}
return averageNumber /= arr.length;
}
现在来看看ES6中的rest运算符
写的场景
function average(...arg){
var averageNumber = 0;
//数组按照从小到大排序
arg.sort(function(a, b){
return a - b;
});
//去掉第一个和最后一个
arg.pop();
arg.shift();
for(var i = 0; i < arg.length; i++){
averageNumber += arg[i];
}
return averageNumber /= arg.length;
}
console.log(average(3, 1, 4, 2));//2.5
此处就是rest运算符的作用;
- 将参数收集起来,收集方式为将参数放入数组存入arg中,所以,下面才可以直接调用数组的方法
再扩展一下写的操作
下面两个案例会让使用更丰富一些
function print(a, b, ...arg){
console.log(a, b, arg);
}
print('a', 'b', 1, 2, 3);
rest运算符前面是可以放指定参数的,并且不会被收集到数组当中
另外一个案例
function print(a, b, ...arg, d){
console.log(a, b, arg);
}
print('a', 'b', 1, 2, 3,'d');
从错误上我们可以了解到rest运算符需要放在参数的最后一位
ES6中读的操作(spreed)
先从一个案例入手
let arr = [1, 2, 3, 4, 5];
console.log(arr); //毫无疑问此处应该打印[1, 2, 3, 4, 5];
console.log(...arr);//但是再spreed运算符后,会变成散列的值: 1, 2, 3, 4, 5
再深入一下使用
let arr1 = [1, 2, 3, 4];
let arr2 = [5, 6, 7, 8];
let arr3 = [...arr1, ...arr2];
console.log(arr3);//[1, 2, 3, 4, 5, 6, 7, 8]
这里arr3通过使用spreed运算符,合成了一个数组,其原理也是通过数组的concat方法拼接在一起
我们再看一个求和的案例,现在按照模块拆分开
function getComputed(...arg){
arg.sort(function(a, b){
return a - b;
});
arg.shift();
arg.prp();
//采用spreed,将数组转成了散列的值
return getSum(...arg);
}
//采用了rest运算符,将散列的值收到数组当中
function getSum(...arg){
let sum = 0;
for(let i = 0; i < arg.length; i++){
sum += arg[i];
}
return sum;
}
从上述的场景中,我们通过第一个函数处理数组(排序,去掉最高分和最低分),再求和
通过…运算发大大的简化了我们的操作
ES7 …运算符对于对象的处理
- 浅层克隆
let company = {
name: 'xinhangdao',
age: 15
}
let department = {
leader: {
name: 'zhangsan',
age: '18'
}
age: 20
}
let obj = {
...company,
...department
}
console.log(obj);
obj.leader.name = "zhangsan";
console.log(obj.leader);//{name: "zhangsan", age: 18}
console.log(department.leader);//{name: "zhangsan", age: 18}
这是打印的结果,但是,这里是浅层克隆,如果修改leader的数据,deparment中的数据也会修改。
实质是,obj拿到的leader是department中leader的引用
要达到深层克隆的效果,有如下办法
let company = {
name: 'xinhangdao',
age: 15
}
let leader: {
name: 'cg',
age: '18'
}
let department = {
age: 20
}
let obj = {
...company,
...department,
leader:{
...leader
}
}
console.log(obj);
obj.leader.name = "zhangsan";
console.log(obj.leader);//{name: "zhangsan", age: 18}
console.log(leader);//{name: "cg", age: 18}
可以通过leader的克隆原始值的方式来深度克隆
但是,此方法,当一个对象有很多层级的时候就不适用了
深度克隆的方法二: js自己写一个deepClone的方法,主要思想是采用递归
深度克隆的方法三: 这是一个剑走偏锋的方法,采用json来做
let obj = {
name: 'zhangsan',
age: 18
}
let obj1 = JSON.parse(JSON.stringify(obj))
但是此方法有缺点:当对象中具有函数的,正则表达式,或者一些特殊的对象,例如new Date()等,可能会使原来的属性丢失,或者改变原有的面貌