詳解ES6 擴(kuò)展運(yùn)算符的使用與注意事項(xiàng)
擴(kuò)展運(yùn)算符 spread syntax
又叫展開語法,寫法是 ...,顧名思義,其實(shí)是用來展開字符串,數(shù)組和對象的一種語法,可以在函數(shù)調(diào)用/數(shù)組構(gòu)造時(shí), 將數(shù)組表達(dá)式或者 string
在語法層面展開;還可以在構(gòu)造字面量對象時(shí), 將對象表達(dá)式按 key-value
的方式展開。常用的語法如下:
//函數(shù)調(diào)用: myFunction(...iterableObj); //字面量數(shù)組構(gòu)造或字符串: [...iterableObj, '4', ...'hello', 6]; // 構(gòu)造字面量對象時(shí),進(jìn)行克隆或者屬性拷貝(ECMAScript 2018規(guī)范新增特性): let objClone = { ...obj };
在函數(shù)調(diào)用時(shí)使用擴(kuò)展運(yùn)算符相當(dāng)于使用 Function.prototype.apply
:
function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction(...args); //相當(dāng)于 function myFunction(x, y, z) {} var args = [0, 1, 2]; myFunction.apply(null, args);
和 apply
不同的是,我們不僅可以將全部參數(shù)放到一個(gè)數(shù)組中,還可以只將其中幾個(gè)參數(shù)用擴(kuò)展運(yùn)算符展開,并且可以再一次調(diào)用中多次使用擴(kuò)展運(yùn)算符。
function myFunction(a, b, c, d, e) { console.log(a, b, c, d, e); //-1 0 1 2 3 console.log(arguments); //[Arguments] { '0': -1, '1': 0, '2': 1, '3': 2, '4': 3 } } var args = [0, 1]; myFunction(-1, ...args, 2, ...[3]);
使用 new
關(guān)鍵字來調(diào)用構(gòu)造函數(shù)時(shí),不能直接使用數(shù)組加上 apply
的方式(apply
執(zhí)行的是調(diào)用 [[Call]]
, 而不是構(gòu)造 [[Construct]])
。有了展開語法, 將數(shù)組展開為構(gòu)造函數(shù)的參數(shù)就很簡單了:
var dateFields = [1970, 0, 1]; // 1970年1月1日 var d = new Date(...dateFields);
如果想要不使用擴(kuò)展運(yùn)算符實(shí)現(xiàn)同樣的效果,我們必須用一個(gè)函數(shù)包裝構(gòu)造函數(shù),將這個(gè)新的構(gòu)造函數(shù)的 prototype
設(shè)為原構(gòu)造函數(shù)的實(shí)例,用 Object.create(constructor.prototype)
(這里主要是為了新構(gòu)造函數(shù)原型的修改不影響原構(gòu)造函數(shù)的原型,直接用 constructor.prototype
作為新構(gòu)造函數(shù)的原型也可以實(shí)現(xiàn))。
function applyAndNew(constructor, args) { function partial() { return constructor.apply(this, args); } if (typeof constructor.prototype === 'object') { partial.prototype = Object.create(constructor.prototype); } return partial; } function myConstructor() { console.log('arguments.length: ' + arguments.length); console.log(arguments); this.prop1 = 'val1'; this.prop2 = 'val2'; } var myArguments = ['hi', 'how', 'are', 'you', 'mr', null]; var myConstructorWithArguments = applyAndNew(myConstructor, myArguments); console.log(new myConstructorWithArguments()); // (myConstructor構(gòu)造函數(shù)中): arguments.length: 6 // (myConstructor構(gòu)造函數(shù)中): ["hi", "how", "are", "you", "mr", null] // ("new myConstructorWithArguments"中): {prop1: "val1", prop2: "val2"}
當(dāng)然用的最多的還是在字面量數(shù)組上,沒有展開語法的時(shí)候,只能組合使用 push, splice, concat 等方法,來將已有數(shù)組元素變成新數(shù)組的一部分。有了展開語法, 通過字面量方式, 構(gòu)造新數(shù)組會(huì)變得更簡單、更優(yōu)雅:
var parts = ['shoulders', 'knees']; var lyrics = ['head', ...parts, 'and', 'toes']; // ["head", "shoulders", "knees", "and", "toes"]
可以用來實(shí)現(xiàn)數(shù)組淺拷貝:
var arr = [1, 2, 3]; var arr2 = [...arr]; // like arr.slice() arr2.push(4); // arr2 此時(shí)變成 [1, 2, 3, 4] // arr 不受影響
連接多個(gè)數(shù)組:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; var arr3 = [...arr1, ...arr2];
擴(kuò)展運(yùn)算符還可以將已有對象的所有可枚舉(enumerable
)屬性拷貝到新構(gòu)造的對象中。該方法為淺拷貝,可以拷貝 Symbol
屬性,但不包含原型上的屬性和方法。如果同時(shí)拷貝多個(gè)對象,后面的對象會(huì)覆蓋前面對象的同名屬性。
var obj1 = { foo: 'bar', x: 42, [Symbol('a')]: 123 }; var obj2 = { foo: 'baz', x: 100, y: 13 }; var clonedObj = { ...obj1 }; console.log(clonedObj); //{ foo: 'bar', x: 42, [Symbol(a)]: 123 } var mergedObj = { ...obj1, ...obj2 }; console.log(mergedObj); //{ foo: 'baz', x: 100, y: 13, [Symbol(a)]: 123 }
該方法的性質(zhì)和 Object.assign
類似,但是 Object.assign()
函數(shù)會(huì)觸發(fā) setters
,而展開語法則不會(huì)。
注意事項(xiàng)
- 在數(shù)組或函數(shù)參數(shù)中使用展開語法時(shí), 擴(kuò)展運(yùn)算符只能用于可迭代對象。
- 只有函數(shù)調(diào)用時(shí),擴(kuò)展運(yùn)算符才可以放在圓括號中,否則會(huì)報(bào)錯(cuò)。
- 只能用在函數(shù)調(diào)用,字面量數(shù)組(可以在數(shù)組中展開字符串),字面量對象中。
- 用于數(shù)組的解構(gòu)賦值的時(shí)候,擴(kuò)展運(yùn)算符只能處于最后一個(gè)。
- 展開對象可以是任意可迭代對象。
剩余參數(shù)
剩余參數(shù)語法允許我們將一個(gè)不定數(shù)量的參數(shù)表示為一個(gè)數(shù)組。如果函數(shù)的最后一個(gè)命名參數(shù)以 ... 為前綴,則它將成為一個(gè)由剩余參數(shù)組成的真數(shù)組,其中從 0(包括)到 theArgs.length
(排除)的元素由傳遞給函數(shù)的實(shí)際參數(shù)提供。
剩余語法(Rest syntax
) 看起來和展開語法完全相同,不同點(diǎn)在于, 剩余參數(shù)用于解構(gòu)數(shù)組和對象。從某種意義上說,剩余語法與展開語法是相反的:展開語法將數(shù)組展開為其中的各個(gè)元素,而剩余語法則是將多個(gè)元素收集起來并“凝聚”為單個(gè)元素。擴(kuò)展運(yùn)算符是用在函數(shù)調(diào)用,而剩余參數(shù)是用在函數(shù)聲明。
剩余參數(shù)和 arguments 對象之間的區(qū)別主要有三個(gè):
- 剩余參數(shù)只包含那些沒有對應(yīng)形參的實(shí)參,而
arguments
對象包含了傳給函數(shù)的所有實(shí)參。 arguments
對象不是一個(gè)真正的數(shù)組,而剩余參數(shù)是真正的 Array 實(shí)例,也就是說你能夠在它上面直接使用所有的數(shù)組方法,比如sort
,map
,forEach
或pop
。arguments
對象還有一些附加的屬性 (如 callee 屬性)。
如果剩余參數(shù)(包括在解構(gòu)賦值中)右側(cè)有逗號,會(huì)拋出 SyntaxError,因?yàn)槭S嘣乇仨毷呛瘮?shù)的最后一個(gè)參數(shù)或者數(shù)組的最后一個(gè)元素。
以上就是詳解ES6 擴(kuò)展運(yùn)算符的詳細(xì)內(nèi)容,更多關(guān)于ES6 擴(kuò)展運(yùn)算符的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript Cookie 直接瀏覽網(wǎng)站分網(wǎng)址
2009-12-12JavaScript實(shí)現(xiàn)頁面定時(shí)刷新(定時(shí)器,meta)
很多朋友看到定時(shí),很容易想到用js定時(shí)器,還有盆友用meta來設(shè)置,下面小編給大家介紹js實(shí)現(xiàn)頁面定時(shí)刷新的方法,一起看看吧2016-10-10js實(shí)現(xiàn)點(diǎn)擊添加一個(gè)input節(jié)點(diǎn)
本文給大家分享的是一段點(diǎn)擊自動(dòng)添加inpu節(jié)點(diǎn)的代碼,非常的簡單實(shí)用,這里推薦給大家。2014-12-12通過JavaScript腳本復(fù)制網(wǎng)頁上的一個(gè)表格
通過JavaScript腳本復(fù)制網(wǎng)頁上的一個(gè)表格...2006-07-07微信JS-SDK坐標(biāo)位置如何轉(zhuǎn)換為百度地圖坐標(biāo)
這篇文章主要介紹了微信JS-SDK坐標(biāo)位置如何轉(zhuǎn)換為百度地圖坐標(biāo) 的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-07-07Javascript實(shí)現(xiàn)的常用算法(如冒泡、快速、鴿巢、奇偶等)
這篇文章主要介紹了Javascript實(shí)現(xiàn)的常用算法,如冒泡、快速、鴿巢、選擇、木桶、奇偶等,需要的朋友可以參考下2014-04-04JS中將圖片base64轉(zhuǎn)file文件的兩種方式
這篇文章主要介紹了JS中圖片base64轉(zhuǎn)file文件的兩種方式,實(shí)現(xiàn)把圖片的base64編碼轉(zhuǎn)成file文件的功能,然后再上傳至服務(wù)器,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02基于JavaScript實(shí)現(xiàn)文件共享型網(wǎng)站
Any?Share?是一種簡單、輕量、快速的文件共享服務(wù)。使用?Javascript?編寫,并搭建在?Firebase?平臺(tái)。本文將利用它實(shí)現(xiàn)創(chuàng)建文件共享型網(wǎng)站,感興趣的可以了解一下2022-11-11