摘要:在語法中,操作符有兩種意義剩余語法,參數(shù)和展開語法,展開數(shù)組對(duì)象,作為函數(shù)數(shù)組對(duì)象的擴(kuò)展運(yùn)算符。使用和參數(shù)進(jìn)行操作其余參數(shù)傳給原始函數(shù)展開語法運(yùn)算則可以看作是參數(shù)的逆運(yùn)算。
在ES6語法中,...操作符有兩種意義:rest(剩余語法,rest參數(shù)) 和 spread(展開語法,展開數(shù)組/對(duì)象),作為函數(shù)、數(shù)組、對(duì)象的擴(kuò)展運(yùn)算符。
從某種意義上說,剩余語法與展開語法是相反的:剩余語法 rest參數(shù)
剩余語法將多個(gè)元素收集起來并“凝聚”為單個(gè)元素,而展開語法則是將數(shù)組/對(duì)象展開為其中的各個(gè)元素。
形式為(...變量名),將一個(gè)不定數(shù)量的參數(shù)表示為一個(gè)數(shù)組。用于獲取函數(shù)實(shí)參中的多余參數(shù),組成一個(gè)數(shù)組,這樣就不需要使用arguments對(duì)象了。
語法
function(a, b, ...theArgs) { // ... }
rest參數(shù)之后不能再有其他參數(shù)(只能是最后一個(gè)參數(shù))否則會(huì)報(bào)錯(cuò)。
函數(shù)的length屬性不包括rest參數(shù)。
(function(a,b,...c){}).length //2
一個(gè)實(shí)例
function sumOnlyNumbers() { var args = arguments; var numbers = filterNumbers(); return numbers.reduce((sum, element) => sum + element); function filterNumbers() { return Array.prototype.filter.call(args, element => typeof element === "number" ); } } sumOnlyNumbers(1, "Hello", 5, false); // => 6
缺點(diǎn): 首先我們要將arguments分配給給一個(gè)臨時(shí)新變量args,這樣才能在內(nèi)部函數(shù)filterNumbers中可以訪問args新變量,因?yàn)?filterNumbers()定義了它自己的arguments 會(huì)覆蓋外部的arguments 。這種做法太冗余了。
優(yōu)化: 使用rest操作符可以靈活解決這個(gè)問題,允許在函數(shù)中定義一個(gè)rest參數(shù) ...args:
function sumOnlyNumbers(...args) { var numbers = filterNumbers(); return numbers.reduce((sum, element) => sum + element); function filterNumbers() { return args.filter(element => typeof element === "number"); } } sumOnlyNumbers(1, "Hello", 5, false); // => 6
剩余參數(shù)只包含那些沒有對(duì)應(yīng)形參的實(shí)參,而 arguments 對(duì)象包含了傳給函數(shù)的所有實(shí)參。
arguments 對(duì)象不是一個(gè)真實(shí)的數(shù)組,而剩余參數(shù)是真實(shí)的 Array實(shí)例。
所以,能夠在剩余參數(shù)上面直接使用所有的數(shù)組方法,比如 sort,map,forEach,pop。
而如果想在arguments對(duì)象上使用數(shù)組方法,你首先得將它轉(zhuǎn)換為真實(shí)的數(shù)組。
[].slice.call(arguments)
arguments 對(duì)象對(duì)象還有一些附加的屬性 (比如callee屬性)。
解構(gòu)賦值let [first,...rest]=[1,2,3,4,5]; first //1 rest //[2,3,4,5]
// ES5 a = list[0], rest = list.slice(1) // ES6 [a, ...rest] = list
const [first, ...rest] = []; first // undefined rest // []
let { x, ...y } = { x: 1, a: 2, b: 3 }; x // 1 y // { a: 2, b: 3 }
// 淺拷貝 let obj = { a: { b: 1 } }; let { ...x } = obj; obj.a.b = 2; x.a.b // 2
// ...運(yùn)算符的解構(gòu)賦值不能繼承自原型對(duì)象的屬性 let o1 = { a: 1 }; let o2 = { b: 2 }; o2.__proto__ = o1; let { ...o3 } = o2; o3 // { b: 2 } o3.a // undefined
const o = Object.create({ x: 1, y: 2 }); o.z = 3; let { x, ...newObj } = o; let { y, z } = newObj; x // 1 y // undefined z // 3
上面代碼中,變量x是單純的解構(gòu)賦值,所以可以讀取對(duì)象o繼承的屬性;變量y和z是擴(kuò)展運(yùn)算符的解構(gòu)賦值,只能讀取對(duì)象o自身的屬性,所以變量z可以賦值成功,變量y取不到值。
ES6 規(guī)定,變量聲明語句之中,如果使用解構(gòu)賦值,擴(kuò)展運(yùn)算符后面必須是一個(gè)變量名,而不能是一個(gè)解構(gòu)賦值表達(dá)式,所以上面代碼引入了中間變量newObj,如果寫成下面這樣會(huì)報(bào)錯(cuò)。
let { x, ...{ y, z } } = o; // SyntaxError: ... must be followed by an identifier in declaration contexts
注意:
解構(gòu)賦值只能放在參數(shù)最后一位,否則會(huì)報(bào)錯(cuò)。
解構(gòu)賦值要求等號(hào)右邊是一個(gè)對(duì)象,如果等號(hào)右邊是undefined或null,就會(huì)報(bào)錯(cuò),因?yàn)樗鼈儫o法轉(zhuǎn)為對(duì)象。
解構(gòu)賦值的拷貝是淺拷貝,即如果一個(gè)鍵的值是復(fù)合類型的值(數(shù)組、對(duì)象、函數(shù))、那么解構(gòu)賦值拷貝的是這個(gè)值的引用,而不是這個(gè)值的副本
...運(yùn)算符的解構(gòu)賦值,不能復(fù)制繼承自原型對(duì)象的屬性
變量聲明語句之中,如果使用解構(gòu)賦值,擴(kuò)展運(yùn)算符后面必須是一個(gè)變量名,而不能是一個(gè)解構(gòu)賦值表達(dá)式
rest參數(shù)&解構(gòu)賦值擴(kuò)展某個(gè)函數(shù)的參數(shù),引入其他操作。
function baseFunction({ a, b }) { // ... } function wrapperFunction({ x, y, ...restConfig }) { // 使用 x 和 y 參數(shù)進(jìn)行操作 // 其余參數(shù)傳給原始函數(shù) return baseFunction(restConfig); }展開語法
spread運(yùn)算則可以看作是rest參數(shù)的逆運(yùn)算。
數(shù)組展開數(shù)組作為參數(shù)序列、復(fù)制數(shù)組、合并數(shù)組、代替apply、...+表達(dá)式
1.展開數(shù)組作為函數(shù)參數(shù)(...arr), 可以將數(shù)組轉(zhuǎn)化為逗號(hào)分隔的參數(shù)序列
console.log(1,...arr) arr1.push(...arr);
注意:push方法的參數(shù)不能是數(shù)組
函數(shù)應(yīng)用實(shí)例
JavaScript 的函數(shù)只能返回一個(gè)值,如果需要返回多個(gè)值,只能返回?cái)?shù)組或?qū)ο蟆U(kuò)展運(yùn)算符提供了解決這個(gè)問題的一種變通方法。
var dateFields = readDateFields(database); var d = new Date(...dateFields);
上面代碼從數(shù)據(jù)庫(kù)取出一行數(shù)據(jù),通過擴(kuò)展運(yùn)算符,直接將其傳入構(gòu)造函數(shù)Date。
2.復(fù)制數(shù)組
const a2 = a1.concat(); // ES5 const itemsCopy = [...items]; // ES6
注意:這兩種方法都是淺拷貝,使用的時(shí)候需要注意。
3.合并數(shù)組
// 合并生成一個(gè)新的數(shù)組,不影響原來的兩個(gè)數(shù)組 arr = [4].concat(list) // ES5 arr = [4, ...list] // ES6
// 擴(kuò)展arr變量,追加arr2 Array.prototype.push.apply(arr, list); // ES5 arr.push(...list); // ES6
如果擴(kuò)展運(yùn)算符后面是一個(gè)空數(shù)組,則不產(chǎn)生任何效果
[...[], 1] // [1]
4.可以替代apply方法,apply要求將參數(shù)合并為數(shù)組,作為參數(shù)傳入
Function.apply(obj,args)方法能接收兩個(gè)參數(shù)
obj:這個(gè)對(duì)象將代替Function類里this對(duì)象
args:這個(gè)是數(shù)組,它將作為參數(shù)傳給Function(args-->arguments)
數(shù)組沒有max方法。Math.max.apply(null,[]);
Math.max.apply(null,[14,3,7]) // ES5寫法 Math.max(...[14,3,7]) // ES6寫法 // 等同于 Math.max(14, 3, 77);
5.擴(kuò)展運(yùn)算符后面還可以放置表達(dá)式。
const arr = [ ...(x > 0 ? ["a"] : []), "b", ];對(duì)象
復(fù)制對(duì)象、完整克隆、合并對(duì)象、...+表達(dá)式、取值函數(shù)get
1.拷貝
let z = { a: 3, b: 4 }; let n = { ...z }; // { a: 3, b: 4 }
這等同于使用Object.assign方法。
let aClone = { ...a }; // 等同于, let aClone = Object.assign({}, a);
上面的例子只是拷貝了對(duì)象實(shí)例的屬性。
2.完整克隆一個(gè)對(duì)象,拷貝實(shí)例屬性+對(duì)象原型的屬性
// 寫法一 const clone1 = { __proto__: Object.getPrototypeOf(obj), ...obj }; // 寫法二 const clone2 = Object.assign( Object.create(Object.getPrototypeOf(obj)), obj ); // 寫法三 const clone3 = Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj) )
上面代碼中,寫法一的__proto__屬性在非瀏覽器的環(huán)境不一定部署,因此推薦使用寫法二和寫法三。
3.合并對(duì)象
// 合并 let ab = { ...a, ...b }; // 等同于, let ab = Object.assign({}, a, b);
如果用戶自定義的屬性,放在擴(kuò)展運(yùn)算符后面,則擴(kuò)展運(yùn)算符內(nèi)部的同名屬性會(huì)被覆蓋掉
let aWithOverrides = { ...a, x: 1, y: 2 }; // 等同于 let aWithOverrides = { ...a, ...{ x: 1, y: 2 } }; // 等同于 let x = 1, y = 2, aWithOverrides = { ...a, x, y }; // 等同于 let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });
上面代碼中,a對(duì)象的x屬性和y屬性,拷貝到新對(duì)象后會(huì)被覆蓋掉。這用來修改現(xiàn)有對(duì)象部分的屬性就很方便了
let newVersion = { ...previousVersion, name: "New Name" // Override the name property };
上面代碼中,newVersion對(duì)象自定義了name屬性,其他屬性全部復(fù)制自previousVersion對(duì)象。
如果把自定義屬性放在擴(kuò)展運(yùn)算符前面,就變成了設(shè)置新對(duì)象的默認(rèn)屬性值。
let aWithDefaults = { x: 1, y: 2, ...a }; // 等同于 let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a); // 等同于 let aWithDefaults = Object.assign({ x: 1, y: 2 }, a);
如果擴(kuò)展運(yùn)算符后面是一個(gè)空對(duì)象,則沒有任何效果。
如果擴(kuò)展運(yùn)算符的參數(shù)是null或undefined,這兩個(gè)值會(huì)被忽略,不會(huì)報(bào)錯(cuò)。
{...{}, a: 1} // { a: 1 } let emptyObject = { ...null, ...undefined }; // 不報(bào)錯(cuò)
4.與數(shù)組的擴(kuò)展運(yùn)算符一樣,對(duì)象的擴(kuò)展運(yùn)算符后面可以跟表達(dá)式。
const obj = { ...(x > 1 ? {a: 1} : {}), b: 2, };
5.對(duì)象中取值函數(shù)get問題
擴(kuò)展運(yùn)算符的參數(shù)對(duì)象之中,如果有取值函數(shù)get,這個(gè)函數(shù)是會(huì)執(zhí)行的
// 并不會(huì)拋出錯(cuò)誤,因?yàn)?x 屬性只是被定義,但沒執(zhí)行 let aWithXGetter = { ...a, get x() { throw new Error("not throw yet"); } }; // 會(huì)拋出錯(cuò)誤,因?yàn)?x 屬性被執(zhí)行了 let runtimeError = { ...a, ...{ get x() { throw new Error("throw now"); } } };字符串
[..."hello"] // [ "h", "e", "l", "l", "o" ]
Unicode 是有兩個(gè)字節(jié)、四字節(jié)之區(qū)分。上面的寫法,有一個(gè)重要的好處,那就是能夠正確識(shí)別四個(gè)字節(jié)的 Unicode 字符。
"xuD83DuDE80y" //"x
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98086.html
摘要:使用新特性開發(fā)微信小程序國(guó)際化與本地化新特性國(guó)際化與本地化新增了很多對(duì)于國(guó)際化的支持,比如時(shí)間格式,貨幣格式,數(shù)字格式等。 ECMAScript 6(簡(jiǎn)稱ES6)是JavaScript語言的最新標(biāo)準(zhǔn)。因?yàn)楫?dāng)前版本的ES6是在2015年發(fā)布的,所以又稱ECMAScript 2015。 微信小程序支持絕大部分ES6的新增特性。 使用ES6新特性開發(fā)微信小程序(1) ES6新特性:Cons...
摘要:目前的標(biāo)準(zhǔn)化工作正在進(jìn)行中,預(yù)計(jì)會(huì)在年月份放出正式敲定的版本。反的方法可以接收一個(gè)參數(shù)并且返回值取決與它的構(gòu)造函數(shù)。之后就可以用這個(gè)返回值做為對(duì)象的鍵了。 本文基于lukehoban/es6features ,同時(shí)參考了大量博客資料,具體見文末引用。 ES6(ECMAScript 6)是即將到來的新版本JavaScript語言的標(biāo)準(zhǔn),代號(hào)harmony(和諧之意,顯然沒有跟上我國(guó)的步伐...
摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會(huì)promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:改動(dòng)函數(shù)的改變不算太大,都是一些其他語言早就有的功能,而一直比較欠缺的,比如函數(shù)參數(shù)默認(rèn)值,任意參數(shù)的表示法,最大的變化應(yīng)該是支持箭頭函數(shù)其他語言稱之為表達(dá)式,一種對(duì)匿名函數(shù)的一種簡(jiǎn)寫方式,以下來探討一下函數(shù)在中的一些改變默認(rèn)參數(shù)任意參數(shù)操 ES6 functions改動(dòng) ????ES6函數(shù)的改變不算太大,都是一些其他語言早就有的功能,而Javascript一直比較欠缺的,比如函數(shù)參數(shù)...
摘要:說到肯定是先介紹了,據(jù)阮一峰老師介紹到,是一個(gè)廣泛使用的轉(zhuǎn)碼器,可以將代碼轉(zhuǎn)為代碼,從而在現(xiàn)有環(huán)境執(zhí)行。輸出其他還有等可以查看阮一峰的入門 ES6也出來有一會(huì)時(shí)間了,他新增的語法糖也的確大大提高了開發(fā)者的效率,今天就總結(jié)一些自己用到最多的。 說到ES6肯定是先介紹Babel了,據(jù)阮一峰老師介紹到,Babel是一個(gè)廣泛使用的轉(zhuǎn)碼器,可以將ES6代碼轉(zhuǎn)為ES5代碼,從而在現(xiàn)有環(huán)境執(zhí)行。這意...
摘要:但是,的本質(zhì)仍然是函數(shù),是構(gòu)造函數(shù)的另外一種寫法。報(bào)錯(cuò)原生構(gòu)造函數(shù)的繼承對(duì)于一些原生的構(gòu)造函數(shù),比如,,,等,在是無法通過方法實(shí)現(xiàn)原生函數(shù)的內(nèi)部屬性,原生函數(shù)內(nèi)部的無法綁定,內(nèi)部屬性獲得不了。 在沒有學(xué)習(xí) ES6 之前,學(xué)習(xí) React,真的是一件非常痛苦的事情。即使之前你對(duì) ES5 有著很好的基礎(chǔ),包括閉包、函數(shù)、原型鏈和繼承,但是 React 中已經(jīng)普遍使用 ES6 的語法,包括 ...
閱讀 1389·2021-10-13 09:39
閱讀 1345·2021-09-23 11:22
閱讀 2255·2019-08-30 14:05
閱讀 1069·2019-08-29 17:03
閱讀 789·2019-08-29 16:24
閱讀 2237·2019-08-29 13:51
閱讀 667·2019-08-29 13:00
閱讀 1324·2019-08-29 11:24