摘要:在可遍歷的量中使用數(shù)組模型數(shù)組解構(gòu)使用一個(gè)迭代器來(lái)獲取數(shù)據(jù)源中的元素。所以,數(shù)組解構(gòu)能夠在上工作的迭代器總是按照元素插入的順序?qū)⒃胤祷?,所以上述的解?gòu)返回的結(jié)果總是相同的。
解構(gòu)賦值(destructuring assignment)語(yǔ)法是一個(gè)Javascript表達(dá)式,這種語(yǔ)法能夠更方便的提取出 Object 或者 Array 中的數(shù)據(jù)。這種語(yǔ)法可以在接受提取的數(shù)據(jù)的地方使用,比如一個(gè)表達(dá)式的左邊。有明確的語(yǔ)法模式來(lái)告訴我們?nèi)绾问褂眠@種語(yǔ)法提取需要的數(shù)據(jù)值。
Object 的解構(gòu)解構(gòu) Object:
const obj = { first: "Jane", last: "Doe" }; const {first: f, last: l} = obj; // f = "Jane"; l = "Doe" // {prop} is short for {prop: prop} const {first, last} = obj; // first = "Jane"; last = "Doe"
解構(gòu)能幫助更好地處理方法返回的對(duì)象:
const obj = { foo: 123 }; const {writable, configurable} = Object.getOwnPropertyDescriptor(obj, "foo"); console.log(writable, configurable); // true trueArray 的解構(gòu)
解構(gòu)數(shù)組,對(duì)所有可遍歷的值有效。
let foo = ["one", "two", "three"]; let [one, two, three] = foo; console.log(one); // "one" console.log(two); // "two" console.log(three); // "three" const iterable = ["a", "b"]; const [x, y] = iterable; // x = "a"; y = "b" [x, y] = iterable; // window.x = "a"; window.y = "b";
同樣的,解構(gòu)數(shù)組也能幫助我們更好地處理函數(shù)返回值:
const [all, year, month, day] = /^(ffffdd)-(dd)-(dd)$/ .exec("2999-12-31");
而且,你也可以忽略你不感興趣的返回值:
function f() { return [1, 2, 3]; } let [a, , b] = f(); console.log(a); // 1 console.log(b); // 3
你也可以忽略全部返回值,不過(guò)似乎沒(méi)啥用:
[,,] = f();
當(dāng)解構(gòu)一個(gè)數(shù)組時(shí),可以使用剩余模式(拓展語(yǔ)句,Spread operator),將數(shù)組剩余部分賦值給一個(gè)變量。
let [a, ...b] = [1, 2, 3]; console.log(a); // 1 console.log(b); // [2, 3]在什么地方可以使用解構(gòu)
解構(gòu)可以在下面這些情景中使用,只展現(xiàn)了數(shù)組模式的演示,對(duì)象模式也是如此。
// 變量聲明: const [x] = ["a"]; let [x] = ["a"]; var [x] = ["a"]; // 賦值: 下面這種情況將會(huì)在全局變量上添加一個(gè) x 屬性,值為‘a(chǎn)‘ [x] = ["a"]; // 參數(shù)的定義: function userId({id}) { return id; } function whois({displayName: displayName, fullName: {firstName: name}}){ console.log(displayName + " is " + name); } var user = { id: 42, displayName: "jdoe", fullName: { firstName: "John", lastName: "Doe" } }; console.log("userId: " + userId(user)); // "userId: 42" whois(user); // "jdoe is John" function f([x]) { ··· } f(["a"]);
也可以在 for-of 循環(huán)中使用:
const arr = ["a", "b"]; for (const [index, element] of arr.entries()) { console.log(index, element); } // Output: // 0 a // 1 b解構(gòu)賦值的模型 patterns
在解構(gòu)中,有下面兩部分參與:
Destructuring source: 解構(gòu)的源,將要被解構(gòu)的數(shù)據(jù),比如解構(gòu)賦值表達(dá)式的右邊部分。
Destructuring target: 解構(gòu)的目標(biāo),比如解構(gòu)復(fù)制表達(dá)式的左邊部分。
解構(gòu)的目標(biāo)可以是下面三個(gè)的任意一個(gè):
賦值對(duì)象,Assigment Patterns。例如 x
賦值對(duì)象通常來(lái)說(shuō)是一個(gè)變量。但是在解構(gòu)賦值中,你有更多的選擇,稍后會(huì)講到。
對(duì)象模型,Object Patterns。比如:{ first: ?pattern?, last: ?pattern? }
數(shù)組模型,Object Patterns。比如:[ ?pattern?, ?pattern? ]
可以任意嵌套模型,而且是可以非常任性的嵌套。
const obj = { a: [{ foo: 123, bar: "abc" }, {}], b: true }; const { a: [{foo: f}] } = obj; // f = 123解構(gòu)的 patterns 如何訪問(wèn)到值的內(nèi)部結(jié)構(gòu)?
在一個(gè)表達(dá)式pattern = someValue中,pattern是如何訪問(wèn)someValue的呢?
Object patterns 將 value 轉(zhuǎn)換成 Object在訪問(wèn)屬性之前,object pattern 將解構(gòu)的源數(shù)據(jù)(destructuing source)轉(zhuǎn)換成對(duì)象。
const {length : len} = "abc"; // len = 3 const {toString: s} = 123; // s = Number.prototype.toString使用“對(duì)象解構(gòu)”的缺點(diǎn)
在這個(gè)過(guò)程中,強(qiáng)制轉(zhuǎn)換成對(duì)象的過(guò)程不是通過(guò)Object()方法,而是通過(guò)內(nèi)置的操作方法toObject()。這兩個(gè)操作處理undefined和null的方式不太一樣。
Object()方法將原始類(lèi)型值轉(zhuǎn)換成包裝類(lèi)型對(duì)象(wrapper object),原來(lái)的值原封不動(dòng)。
> typeof Object("abc") "object" > var obj = {}; > Object(obj) === obj true
也會(huì)將undefined 和 null 轉(zhuǎn)換成一個(gè)空的對(duì)象。
> Object(undefined) {} > Object(null) {}
對(duì)比之下,當(dāng)遇到undefined和null的時(shí)候,toObject()方法則會(huì)拋出一個(gè)錯(cuò)誤。所以下面的解構(gòu)是失敗的:
const { prop: x } = undefined; // TypeError const { prop: y } = null; // TypeError
因此,你可以使用空對(duì)象模型{}來(lái)檢查一個(gè)值是否被強(qiáng)制轉(zhuǎn)換成了一個(gè)對(duì)象。正如前面提到的規(guī)則,undefined和null將會(huì)拋出錯(cuò)誤
({} = [true, false]); // OK, Arrays are coercible to objects ({} = "abc"); // OK, strings are coercible to objects ({} = undefined); // TypeError ({} = null); // TypeError
表達(dá)式兩邊的括號(hào)是必須的,因?yàn)樵?JavaScript 中,聲明不能以花括號(hào)開(kāi)始。
在可遍歷的量中使用數(shù)組模型數(shù)組解構(gòu)使用一個(gè)迭代器來(lái)獲取數(shù)據(jù)源中的元素。因此,你可以對(duì)任何可以遍歷的值使用數(shù)組解構(gòu)。
字符串是可遍歷的:
const [x, ...y] = "abc"; // x="a"; y=["b", "c"]
我們無(wú)法通過(guò)索引訪問(wèn) Set中的元素,但是可以通過(guò)迭代器。所以,數(shù)組解構(gòu)能夠在 Sets上工作:
const [x,y] = new Set(["a", "b"]); // x="a"; y="b’;
Set的迭代器總是按照元素插入的順序?qū)⒃胤祷?,所以上述的解?gòu)返回的結(jié)果總是相同的。
使用“數(shù)組解構(gòu)”的缺點(diǎn)如果一個(gè)值有一個(gè) key 為Symbol.iterator的方法,這個(gè)方法返回的是一個(gè)對(duì)象,那么這個(gè)值是可以遍歷的。如果被解構(gòu)的值不能遍歷的,那么“數(shù)組解構(gòu)”會(huì)拋出一個(gè)TypeError錯(cuò)誤。
let x; [x] = [true, false]; // OK, Arrays are iterable [x] = "abc"; // OK, strings are iterable [x] = { * [Symbol.iterator]() { yield 1 } }; // OK, iterable [x] = {}; // TypeError, empty objects are not iterable [x] = undefined; // TypeError, not iterable [x] = null; // TypeError, not iterable
可以用一個(gè)空的數(shù)組模型[]來(lái)檢查值是不是可遍歷的:
[] = {}; // TypeError, empty objects are not iterable [] = undefined; // TypeError, not iterable [] = null; // TypeError, not iterable默認(rèn)值
默認(rèn)值是可選的,在數(shù)據(jù)源中找不到對(duì)應(yīng)的值時(shí),如果設(shè)置了默認(rèn)值,則匹配這個(gè)默認(rèn)值作為匹配結(jié)果,否則返回 undefined。
const [x=3, y] = []; // x = 3; y = undefined。 const {foo: x=3, bar: y} = {}; // x = 3; y = undefinedundefined 也會(huì)觸發(fā)默認(rèn)值
當(dāng)解構(gòu)模式有匹配結(jié)果,且匹配結(jié)果是 undefined 時(shí),也會(huì)使用默認(rèn)值作為返回結(jié)果:
const [x=1] = [undefined]; // x = 1 const {prop: y=2} = {prop: undefined}; // y = 2默認(rèn)值是根據(jù)需要計(jì)算出來(lái)的
也就是說(shuō)下面的解構(gòu):
const {prop: y=someFunc()} = someValue;
相當(dāng)于:
let y; if (someValue.prop === undefined) { y = someFunc(); } else { y = someValue.prop; }
使用console.log()可以觀察到:
> function log(x) { console.log(x); return "YES" } > const [a=log("hello")] = []; > a "YES" > const [b=log("hello")] = [123]; > b 123
在第二個(gè)解構(gòu)中,默認(rèn)值沒(méi)有觸發(fā),并且log()沒(méi)有被調(diào)用。
默認(rèn)值可以引用模式中的其他變量默認(rèn)值可以引用模式中的任何變量,包括相同模式中的其他變量:
const [x=3, y=x] = []; // x=3; y=3 const [x=3, y=x] = [7]; // x=7; y=7 const [x=3, y=x] = [7, 2]; // x=7; y=2
但是,變量的順序很關(guān)鍵,從左到右,先聲明的變量不能引用后聲明的變量,也就是左邊的不能引用右邊的。
const [x=y, y=3] = []; // ReferenceErrorpatterns 的默認(rèn)值
到目前為止,我們所看到的都是模式中變量的默認(rèn)值,我們也可以為模式設(shè)置默認(rèn)值。
const [{prop: x} = {}] = [];
如果整個(gè)模式?jīng)]有匹配結(jié)果,則使用{}作為數(shù)據(jù)源來(lái)匹配。
const { prop: x } = {}; // x = undefined
上面的例子中,x 為 undefined 可能還是不夠直觀。看下面這個(gè)例子:
const [{prop: x} = {props: "abc"}] = []; // x=abc對(duì)象解構(gòu)的更多特性 屬性,屬性值的簡(jiǎn)寫(xiě)
如果屬性值是一個(gè)變量,和屬性的 key相同,就可以忽略這個(gè) key:
const { x, y } = { x: 11, y: 8 }; // x = 11; y = 8 // 等價(jià)于 const { x: x, y: y } = { x: 11, y: 8 };計(jì)算后的屬性的鍵
如果把表達(dá)式放入方括號(hào)中,可以用這個(gè)表達(dá)式聲明屬性的鍵:
const FOO = "foo"; const { [FOO]: f} = {fooL 123}; // f = 123
這也使得可以使用 symbols 來(lái)做屬性的鍵:
// Create and destructure a property whose key is a symbol const KEY = Symbol(); const obj = { [KEY]: "abc" }; const { [KEY]: x } = obj; // x = "abc" // Extract Array.prototype[Symbol.iterator] const { [Symbol.iterator]: func } = []; console.log(typeof func); // function數(shù)組解構(gòu)的更多特性 省略
在解構(gòu)的過(guò)程中可以跳過(guò)一些元素:
const [,,x,y] = [1,2,3,4]; // x= 3 y = 4;剩余運(yùn)算符 Rest operator (...)
剩余運(yùn)算符可以將一個(gè)可遍歷對(duì)象中剩余的元素提取到一個(gè)數(shù)組中。如果這個(gè)運(yùn)算符在數(shù)組模式中使用,運(yùn)算符必須放在最后:
const [x, ...y] = [1,2,3,4]; // x=1; y=[2,3,4];
要注意的時(shí),拓展運(yùn)算符(spread operator)與剩余操作符有著相同的語(yǔ)法-三個(gè)點(diǎn)。但是它們之間有區(qū)別:前者將數(shù)組變成多個(gè)元素;后者則用來(lái)解構(gòu)和提取數(shù)據(jù),多個(gè)元素壓縮成一個(gè)元素。
如果運(yùn)算符找不到任何元素,將會(huì)匹配一個(gè)空的數(shù)組,永遠(yuǎn)不會(huì)返回undefined 或者 null。例如:
const [x, y, ...z] = ["a"]; // x="a"; y=undefined; z
操作符不一定非要是一個(gè)變量,也可以使用模式:
const [x, ...[y, z]] = ["a", "b", "c"]; // x = "a"; y = "b"; z = "c"解構(gòu)的陷阱
在使用解構(gòu)的時(shí)候,有兩點(diǎn)要考慮清楚:
不能使用大括號(hào)作為聲明語(yǔ)句的開(kāi)頭;
在解構(gòu)的過(guò)程中,可以申明變量或者分配給變量,但是不能同時(shí)這么做;
解構(gòu)的幾個(gè)例子在 for-of 中使用解構(gòu):
const map = new Map().set(false, "no").set(true, "yes"); for (const [key, value] of map) { console.log(key + " is " + value); }
使用解構(gòu)交換兩個(gè)變量的值:
[a, b] = [b, a];
或者:
[a, b, c] = [c, a, b];
還可以分割數(shù)據(jù):
const [first, ...rest] = ["a", "b", "c"]; // first = "a"; rest = ["b", "c"]
處理方法返回的數(shù)組更加方便:
const [all, year, month, day] = /^(ffffdd)-(dd)-(dd)$/.exec("2999-12-31"); const cells = "Jane Doe CTO" const [firstName, lastName, title] = cells.split(" "); console.log(firstName, lastName, title);
要注意的一點(diǎn)是:exec等一些方法可能會(huì)返回 null,導(dǎo)致程序拋出錯(cuò)誤TypeError,此時(shí)需要添加一個(gè)默認(rèn)值:
const [, year, month, day] = /^(ffffdd)-(dd)-(dd)$/.exec(someStr) || [];
參考資料:
Exploringjs Destructuring
MDN Destructing assignment
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/88093.html
摘要:解構(gòu),一種黑魔法解構(gòu)是從對(duì)象中提取出更小元素的過(guò)程。賦值是對(duì)解構(gòu)出來(lái)的元素進(jìn)行重新賦值??偨Y(jié)本章講解了對(duì)象解構(gòu)賦值和數(shù)組解構(gòu)賦值,以及對(duì)象和數(shù)組混合情況下的解構(gòu)賦值操作,最后一個(gè)知識(shí)點(diǎn)是解構(gòu)函數(shù)的參數(shù)。 解構(gòu),一種黑魔法 解構(gòu)是從對(duì)象中提取出更小元素的過(guò)程。賦值是對(duì)解構(gòu)出來(lái)的元素進(jìn)行重新賦值。 下面的代碼你可能無(wú)法在瀏覽器上實(shí)時(shí)測(cè)試,推薦在babel官網(wǎng)在線測(cè)試代碼:在線測(cè)試ES6代碼...
摘要:對(duì)象解構(gòu)如果使用解析聲明變量,則必須提供初始化程序也就是等號(hào)右側(cè)的值以下語(yǔ)句有語(yǔ)法錯(cuò)誤解構(gòu)賦值表達(dá)式也就是右側(cè)的表達(dá)式如果為或會(huì)導(dǎo)致程序拋出錯(cuò)誤,因?yàn)槿魏螄L試讀取或的屬性的行為都會(huì)觸發(fā)運(yùn)行時(shí)錯(cuò)誤上面代碼是聲明變量同時(shí)賦值相應(yīng)的屬性值那如果已 對(duì)象解構(gòu) 如果使用var、let、const解析聲明變量,則必須提供初始化程序(也就是等號(hào)右側(cè)的值)以下語(yǔ)句有語(yǔ)法錯(cuò)誤 var { type, n...
摘要:對(duì)象解構(gòu)如果使用解析聲明變量,則必須提供初始化程序也就是等號(hào)右側(cè)的值以下語(yǔ)句有語(yǔ)法錯(cuò)誤解構(gòu)賦值表達(dá)式也就是右側(cè)的表達(dá)式如果為或會(huì)導(dǎo)致程序拋出錯(cuò)誤,因?yàn)槿魏螄L試讀取或的屬性的行為都會(huì)觸發(fā)運(yùn)行時(shí)錯(cuò)誤上面代碼是聲明變量同時(shí)賦值相應(yīng)的屬性值那如果已 對(duì)象解構(gòu) 如果使用var、let、const解析聲明變量,則必須提供初始化程序(也就是等號(hào)右側(cè)的值)以下語(yǔ)句有語(yǔ)法錯(cuò)誤 var { type, n...
摘要:當(dāng)冒號(hào)右側(cè)存在花括號(hào)時(shí),表示目標(biāo)被嵌套在對(duì)象的更深一層中。在對(duì)象的嵌套解構(gòu)中同樣能為本地變量使用不同的名稱(chēng)提取數(shù)組解構(gòu)結(jié)構(gòu)賦值基本忽略一些選項(xiàng)重新賦值默認(rèn)值數(shù)組解構(gòu)賦值同樣允許在數(shù)組任意位置指定默認(rèn)值。 主要知識(shí)點(diǎn):對(duì)象解構(gòu)、數(shù)組解構(gòu)、混合解構(gòu)以及參數(shù)解構(gòu)showImg(https://segmentfault.com/img/bVbfWgH?w=1020&h=585); 《深入理解...
閱讀 2665·2021-11-25 09:43
閱讀 1919·2021-09-22 15:26
閱讀 3949·2019-08-30 15:56
閱讀 1787·2019-08-30 15:55
閱讀 1957·2019-08-30 15:54
閱讀 872·2019-08-30 15:52
閱讀 3228·2019-08-29 16:23
閱讀 964·2019-08-29 12:43