扩展运算符:…运算符html
好处:简化书写长度,提高开发效率。es6
一、展开功能数组
二、收集功能babel
因此…运算符又能够叫作展开收集运算符。app
他的不一样做用须要在不一样场景中使用才会出现:函数
a、读 - 展开做用,输出、打印的状况。读完输出散列的值es5
读取arg2这个数组,并返回散列的项spa
1 var arg2 = [1,2,3,4,5]; 2 3 console.log(...arg2);// 读,展开数组成散列的项
b、写 - 收集做用,写入、整合的状况。写完获得一个数组prototype
把实参这些散列项写入到args里边并返回一个数组3d
function test(...args){ console.log(args);//写,把散列的项写入到一个数组中 } test(1,2,3,4,6);
不光这一种用法,他还能够有选择性的写:
以下图,把扩展运算符写到最后,前边有单独的行参:
* 可是尝试把…写在行参中间,就会报错:
var arg2 = [1,2,3,4,5]; console.log(...arg2);// 读,展开数组成散列的项 // 好比写…[1,2,3] 至关于写 1,2,3
观察了一下babel编译后的代码,是让log调用时使用apply的原理调用:
往apply的第二个参数处传入一个数组,数组在apply内部就会被一一展开成一个参数列表,log接收到的就是这个展开的参数列表,
执行console.log再次打印就是这个参数列表被一一打印了。这么看来apply也有展开数组的做用。
1 // 读操做 - 数组合并 2 3 let arr1 = [1,2,3,4], 4 5 arr2 = [6,7,8,9], 6 7 newArr = [...arr1,...arr2]; 8 9 console.log(newArr); 10 11 // 至关于下边的写法: 12 13 let concatArr = [].concat(arr1,arr2); 14 15 console.log(concatArr);
实际上babel编译后确实是这么处理的:
这也是他语法糖的说明。
这种方法若是用来作数组克隆的话,也是一种浅克隆。举例说明:
1 var arrA = [{ 2 a: 1, 3 b: 1 4 }, 5 'b', 6 { 7 a: 2, 8 b: 2 9 } 10 ]; 11 var arrB = [...arrA]; 12 console.log(arrB) arrB[0].a = '浅克隆?'; 13 arrB[1] = '浅克隆!'; 14 console.log('arrA:', arrA, 'arrB', arrB);
打印结果:
好比咱们写一个求和函数:
1 function getSum() { 2 let len = arguments.length, 3 sum = 0; 4 for (let i = 0; i < len; i++) { 5 sum += arguments[i] 6 } 7 return sum 8 } 9 console.log(getSum(1, 2, 3, 4, 6));
这样写的原理是利用arguments实质为一个伪数组,遍历这个伪数组,把每一项累加求和。
由于之因此叫伪数组,就是由于他们是假数组,不能为所欲为的用数组的方法(好比forEach遍历),必须经过转换。
【更多伪数组转换为数组的方法见这里】http://www.javashuo.com/article/p-ksstmqgk-km.html:
若是咱们想用数组的方法,就得把arguments这个伪数组转化为数组再进行处理。
1 function getSum() { 2 let arr = Array.prototype.slice.call(arguments); // 转换伪数组为真数组。 3 return arr.reduce((pre, cur) => { 4 return pre += cur; 5 }, 0); 6 } 7 console.log(getSum(1, 2, 3, 4, 6));
奇迹就是,当咱们利用扩展运算符的收集做用后,咱们就能够直接使用扩展运算符收集后的结果,而这个结果就是一个数组格式:
1 function getSum(...arr) { 2 // let arr = Array.prototype.slice.call(arguments);为了和上边作清晰的对比,我直接注视了这一句而不是直接删掉了。 3 return arr.reduce((pre, cur) = >{ 4 return pre += cur 5 }, 6 0) 7 } 8 console.log(getSum(1, 2, 3, 4, 6));
在有扩展运算符的协助下,咱们想在求和函数中新增点功能:先排序去掉最大值和最小值后求平均数
如此直接用数组的方法就更方便了:
好比咱们能够先用Array的sort函数排序、再用pop、shift去掉先后两项,以后再用forEach或者reduce求和,最后用和/arr.length这个简单的思路实现。
实现起来一鼓作气,毕竟扩展运算符收集的就是一个数组,不用原生方法就浪费了。
这样我不只开始怀疑扩展运算符收集做用的原理就是一个函数接收多个实参后将arguments转换为了真数组。
我把以上代码使用babel进行转换,获得编译后代码以下图右侧代码:
虽然转换伪数组为真数组的作法和咱们的经常使用写法不同,可是es5转换后代码的根本就是将arguments伪数组转换为数组并使用。
却是给咱们提供了另外一种转换伪数组的方法。
es6的扩展运算符只能展开一个数组
在es7中能够展开一个对象,但必须是在对象里边使用扩展运算符展开对象,且不能让对象在数组中展开([…{}]这种展开须要iterator)。
扩展对象举例 - 相似下面这种写法:
获得的obj2以下:
可见,obj里边的键值对被克隆到了obj2当中。
这段代码被babel后的样子见下边:
和他的做用看上去同样,被babel编译后的代码就是一层拷贝。可是有点特殊的是,他是一种浅拷贝(其余深浅拷贝方法的合集见相关笔记章节):
为了证实他是浅拷贝,我把代码稍微修改,增长一个引用类型的属性值:
获得obj.IDCard.address和obj2修改后的同样,都是'Hang Zhou CHINA';
多提另外一种克隆方法:
语法:Object.assign(目标对象,克隆对象1,克隆对象2);
会以浅克隆的方式,将后边对象的值复制到目标对象里边去。
一样,再来对比一下:
2019-05-04 17:06:09