export default withRouter((props) => <DigitalMuseum {...props} />);
最近在寫react吟税,經(jīng)常看到類似這種代碼,決定要把...es6語(yǔ)法搞清楚,發(fā)現(xiàn)這篇文章非常清晰
https://blog.csdn.net/qq_30100043/article/details/53391308#
1 含義
擴(kuò)展運(yùn)算符( spread )是三個(gè)點(diǎn)(...)乎串。它好比 rest 參數(shù)的逆運(yùn)算店枣,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列速警。
1. console.log(...[1, 2, 3])
2. // 1 2 3
3. console.log(1, ...[2, 3, 4], 5)
4. // 1 2 3 4 5
5. [...document.querySelectorAll('div')]
6. // [<div>, <div>, <div>]
該運(yùn)算符主要用于函數(shù)調(diào)用。
1. function push(array, ...items) {
2. array.push(...items);
3. }
4. function add(x, y) {
5. return x + y;
6. }
7. var numbers = [4, 38];
8. add(...numbers) // 42
上面代碼中鸯两,array.push(...items)和add(...numbers)這兩行闷旧,都是函數(shù)的調(diào)用,它們的都使用了擴(kuò)展運(yùn)算符钧唐。該運(yùn)算符將一個(gè)數(shù)組忙灼,變?yōu)閰?shù)序列。
擴(kuò)展運(yùn)算符與正常的函數(shù)參數(shù)可以結(jié)合使用钝侠,非常靈活该园。
1. function f(v, w, x, y, z) { }
2. var args = [0, 1];
3. f(-1, ...args, 2, ...[3]);
2 替代數(shù)組的 apply 方法
由于擴(kuò)展運(yùn)算符可以展開數(shù)組,所以不再需要apply方法帅韧,將數(shù)組轉(zhuǎn)為函數(shù)的參數(shù)了里初。
1. // ES5 的寫法
2. function f(x, y, z) {
3. // ...
4. }
5. var args = [0, 1, 2];
6. f.apply(null, args);
7. // ES6 的寫法
8. function f(x, y, z) {
9. // ...
10. }
11. var args = [0, 1, 2];
12. f(...args);
下面是擴(kuò)展運(yùn)算符取代apply方法的一個(gè)實(shí)際的例子,應(yīng)用Math.max方法忽舟,簡(jiǎn)化求出一個(gè)數(shù)組最大元素的寫法双妨。
1. // ES5 的寫法
2. Math.max.apply(null, [14, 3, 77])
3. // ES6 的寫法
4. Math.max(...[14, 3, 77])
5. // 等同于
6. Math.max(14, 3, 77);
上面代碼表示,由于 JavaScript 不提供求數(shù)組最大元素的函數(shù)叮阅,所以只能套用Math.max函數(shù)刁品,將數(shù)組轉(zhuǎn)為一個(gè)參數(shù)序列,然后求最大值浩姥。有了擴(kuò)展運(yùn)算符以后挑随,就可以直接用Math.max了。
另一個(gè)例子是通過push函數(shù)勒叠,將一個(gè)數(shù)組添加到另一個(gè)數(shù)組的尾部兜挨。
1. // ES5 的寫法
2. var arr1 = [0, 1, 2];
3. var arr2 = [3, 4, 5];
4. Array.prototype.push.apply(arr1, arr2);
5. // ES6 的寫法
6. var arr1 = [0, 1, 2];
7. var arr2 = [3, 4, 5];
8. arr1.push(...arr2);
上面代碼的 ES5 寫法中,push方法的參數(shù)不能是數(shù)組缴饭,所以只好通過apply方法變通使用push方法暑劝。有了擴(kuò)展運(yùn)算符,就可以直接將數(shù)組傳入push方法颗搂。
下面是另外一個(gè)例子担猛。
1. // ES5
2. new (Date.bind.apply(Date, [null, 2015, 1, 1]))
3. // ES6
4. new Date(...[2015, 1, 1]);
3 擴(kuò)展運(yùn)算符的應(yīng)用
( 1 )合并數(shù)組
擴(kuò)展運(yùn)算符提供了數(shù)組合并的新寫法。
1. // ES5
2. [1, 2].concat(more)
3. // ES6
4. [1, 2, ...more]
5. var arr1 = ['a', 'b'];
6. var arr2 = ['c'];
7. var arr3 = ['d', 'e'];
8. // ES5 的合并數(shù)組
9. arr1.concat(arr2, arr3);
10. // [ 'a', 'b', 'c', 'd', 'e' ]
11. // ES6 的合并數(shù)組
12. [...arr1, ...arr2, ...arr3]
13. // [ 'a', 'b', 'c', 'd', 'e' ]
( 2 )與解構(gòu)賦值結(jié)合
擴(kuò)展運(yùn)算符可以與解構(gòu)賦值結(jié)合起來(lái),用于生成數(shù)組傅联。
1. // ES5
2. a = list[0], rest = list.slice(1)
3. // ES6
4. [a, ...rest] = list
5. 下面是另外一些例子先改。
6. const [first, ...rest] = [1, 2, 3, 4, 5];
7. first // 1
8. rest // [2, 3, 4, 5]
9. const [first, ...rest] = [];
10. first // undefined
11. rest // []:
12. const [first, ...rest] = ["foo"];
13. first // "foo"
14. rest // []
如果將擴(kuò)展運(yùn)算符用于數(shù)組賦值,只能放在參數(shù)的最后一位蒸走,否則會(huì)報(bào)錯(cuò)仇奶。
1. const [...butLast, last] = [1, 2, 3, 4, 5];
2. // 報(bào)錯(cuò)
3. const [first, ...middle, last] = [1, 2, 3, 4, 5];
4. // 報(bào)錯(cuò)
( 3 )函數(shù)的返回值
JavaScript 的函數(shù)只能返回一個(gè)值,如果需要返回多個(gè)值比驻,只能返回?cái)?shù)組或?qū)ο蟾盟荨U(kuò)展運(yùn)算符提供了解決這個(gè)問題的一種變通方法。
1. var dateFields = readDateFields(database);
2. var d = new Date(...dateFields);
上面代碼從數(shù)據(jù)庫(kù)取出一行數(shù)據(jù)别惦,通過擴(kuò)展運(yùn)算符狈茉,直接將其傳入構(gòu)造函數(shù)Date。
( 4 )字符串
擴(kuò)展運(yùn)算符還可以將字符串轉(zhuǎn)為真正的數(shù)組掸掸。
1. [...'hello']
2. // [ "h", "e", "l", "l", "o" ]
上面的寫法氯庆,有一個(gè)重要的好處,那就是能夠正確識(shí)別 32 位的 Unicode 字符扰付。
1. 'x\uD83D\uDE80y'.length // 4
2. [...'x\uD83D\uDE80y'].length // 3
上面代碼的第一種寫法堤撵, JavaScript 會(huì)將 32 位 Unicode 字符,識(shí)別為 2 個(gè)字符羽莺,采用擴(kuò)展運(yùn)算符就沒有這個(gè)問題实昨。因此,正確返回字符串長(zhǎng)度的函數(shù)禽翼,可以像下面這樣寫屠橄。
1. function length(str) {
2. return [...str].length;
3. }
4. length('x\uD83D\uDE80y') // 3
凡是涉及到操作 32 位 Unicode 字符的函數(shù),都有這個(gè)問題闰挡。因此锐墙,最好都用擴(kuò)展運(yùn)算符改寫。
1. let str = 'x\uD83D\uDE80y';
2. str.split('').reverse().join('')
3. // 'y\uDE80\uD83Dx'
4. [...str].reverse().join('')
5. // 'y\uD83D\uDE80x'
上面代碼中长酗,如果不用擴(kuò)展運(yùn)算符溪北,字符串的reverse操作就不正確。
( 5 )實(shí)現(xiàn)了 Iterator 接口的對(duì)象
任何 Iterator 接口的對(duì)象夺脾,都可以用擴(kuò)展運(yùn)算符轉(zhuǎn)為真正的數(shù)組之拨。
1. var nodeList = document.querySelectorAll('div');
2. var array = [...nodeList];
上面代碼中,querySelectorAll方法返回的是一個(gè)nodeList對(duì)象咧叭。它不是數(shù)組蚀乔,而是一個(gè)類似數(shù)組的對(duì)象。這時(shí)菲茬,擴(kuò)展運(yùn)算符可以將其轉(zhuǎn)為真正的數(shù)組吉挣,原因就在于NodeList對(duì)象實(shí)現(xiàn)了 Iterator 接口派撕。
對(duì)于那些沒有部署 Iterator 接口的類似數(shù)組的對(duì)象,擴(kuò)展運(yùn)算符就無(wú)法將其轉(zhuǎn)為真正的數(shù)組睬魂。
1. let arrayLike = {
2. '0': 'a',
3. '1': 'b',
4. '2': 'c',
5. length: 3
6. };
7. // TypeError: Cannot spread non-iterable object.
8. let arr = [...arrayLike];
上面代碼中终吼,arrayLike是一個(gè)類似數(shù)組的對(duì)象,但是沒有部署 Iterator 接口氯哮,擴(kuò)展運(yùn)算符就會(huì)報(bào)錯(cuò)际跪。這時(shí),可以改為使用Array.from方法將arrayLike轉(zhuǎn)為真正的數(shù)組喉钢。
( 6 ) Map 和 Set 結(jié)構(gòu)姆打, Generator 函數(shù)
擴(kuò)展運(yùn)算符內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的 Iterator 接口,因此只要具有 Iterator 接口的對(duì)象出牧,都可以使用擴(kuò)展運(yùn)算符穴肘,比如 Map 結(jié)構(gòu)。
1. let map = new Map([
2. [1, 'one'],
3. [2, 'two'],
4. [3, 'three'],
5. ]);
6. let arr = [...map.keys()]; // [1, 2, 3]
Generator 函數(shù)運(yùn)行后舔痕,返回一個(gè)遍歷器對(duì)象,因此也可以使用擴(kuò)展運(yùn)算符豹缀。
1. var go = function*(){
2. yield 1;
3. yield 2;
4. yield 3;
5. };
6. [...go()] // [1, 2, 3]
上面代碼中伯复,變量go是一個(gè) Generator 函數(shù),執(zhí)行后返回的是一個(gè)遍歷器對(duì)象邢笙,對(duì)這個(gè)遍歷器對(duì)象執(zhí)行擴(kuò)展運(yùn)算符啸如,就會(huì)將內(nèi)部遍歷得到的值,轉(zhuǎn)為一個(gè)數(shù)組氮惯。
如果對(duì)沒有iterator接口的對(duì)象叮雳,使用擴(kuò)展運(yùn)算符,將會(huì)報(bào)錯(cuò)妇汗。
1. var obj = {a: 1, b: 2};
2. let arr = [...obj]; // TypeError: Cannot spread non-iterable object