擴展運算符:…運算符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