ES6解構(gòu)賦值

前面的話

我們經(jīng)常定義許多對(duì)象和數(shù)組,然后有組織地從中提取相關(guān)的信息片段。在ES6中添加了可以簡(jiǎn)化這種任務(wù)的新特性:解構(gòu)。解構(gòu)是一種打破數(shù)據(jù)結(jié)構(gòu)嫂便,將其拆分為更小部分的過(guò)程。本文將詳細(xì)介紹ES6解構(gòu)賦值

引入

在ES5中闸与,開(kāi)發(fā)者們?yōu)榱藦膶?duì)象和數(shù)組中獲取特定數(shù)據(jù)并賦值給變量毙替,編寫(xiě)了許多看起來(lái)同質(zhì)化的代碼

let options = {
    repeat: true,
    save: false
};
// 從對(duì)象中提取數(shù)據(jù)
let repeat = options.repeat,
save = options.save;

這段代碼從options對(duì)象中提取repeat和save的值,并將其存儲(chǔ)為同名局部變量践樱,提取的過(guò)程極為相似

如果要提取更多變量厂画,則必須依次編寫(xiě)類似的代碼來(lái)為變量賦值,如果其中還包含嵌套結(jié)構(gòu)映胁,只靠遍歷是找不到真實(shí)信息的木羹,必須要深入挖掘整個(gè)數(shù)據(jù)結(jié)構(gòu)才能找到所需數(shù)據(jù)

所以ES6添加了解構(gòu)功能,將數(shù)據(jù)結(jié)構(gòu)打散的過(guò)程變得更加簡(jiǎn)單解孙,可以從打散后更小的部分中獲取所需信息

對(duì)象解構(gòu)

對(duì)象字面量的語(yǔ)法形式是在一個(gè)賦值操作符左邊放置一個(gè)對(duì)象字面量

let node = {
    type: "Identifier",
    name: "foo"
};
let { type, name } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"

在這段代碼中坑填,node.type的值被存儲(chǔ)在名為type的變量中;node.name的值被存儲(chǔ)在名為name的變量中

【解構(gòu)賦值】

到目前為止弛姜,我們已經(jīng)將對(duì)象解構(gòu)應(yīng)用到了變量的聲明中脐瑰。然而,我們同樣可以在給變量賦值時(shí)使用解構(gòu)語(yǔ)法

let node = {
    type: "Identifier",
    name: "foo"
},
type = "Literal",
name = 5;
// 使用解構(gòu)來(lái)分配不同的值
({ type, name } = node);
console.log(type); // "Identifier"
console.log(name); // "foo"

在這個(gè)示例中廷臼,聲明變量type和name時(shí)初始化了一個(gè)值苍在,在后面幾行中绝页,通過(guò)解構(gòu)賦值的方法,從node對(duì)象讀取相應(yīng)的值重新為這兩個(gè)變量賦值

[注意]一定要用一對(duì)小括號(hào)包裹解構(gòu)賦值語(yǔ)句寂恬,JS引擎將一對(duì)開(kāi)放的花括號(hào)視為一個(gè)代碼塊续誉。語(yǔ)法規(guī)定,代碼塊語(yǔ)句不允許出現(xiàn)在賦值語(yǔ)句左側(cè)初肉,添加小括號(hào)后可以將塊語(yǔ)句轉(zhuǎn)化為一個(gè)表達(dá)式酷鸦,從而實(shí)現(xiàn)整個(gè)解構(gòu)賦值過(guò)程

解構(gòu)賦值表達(dá)式的值與表達(dá)式右側(cè)(也就是=右側(cè))的值相等,如此一來(lái)牙咏,在任何可以使用值的地方都可以使用解構(gòu)賦值表達(dá)式

let node = {
    type: "Identifier",
    name: "foo"
},
type = "Literal",
name = 5;
function outputInfo(value) {
    console.log(value === node); // true
}
outputInfo({ type, name } = node);
console.log(type); // "Identifier"
console.log(name); // "foo"

調(diào)用outputlnfo()函數(shù)時(shí)傳入了一個(gè)解構(gòu)表達(dá)式臼隔,由于JS表達(dá)式的值為右側(cè)的值,因而此處傳入的參數(shù)等同于node妄壶,且變量type和name被重新賦值摔握,最終將node傳入outputlnfo()函數(shù)

[注意]解構(gòu)賦值表達(dá)式(也就是=右側(cè)的表達(dá)式)如果為null或undefined會(huì)導(dǎo)致程序拋出錯(cuò)誤。也就是說(shuō)丁寄,任何嘗試讀取null或undefined的屬性的行為都會(huì)觸發(fā)運(yùn)行時(shí)錯(cuò)誤

【默認(rèn)值】

使用解構(gòu)賦值表達(dá)式時(shí)氨淌,如果指定的局部變量名稱在對(duì)象中不存在,那么這個(gè)局部變量會(huì)被賦值為undefined

let node = {
    type: "Identifier",
    name: "foo"
};
let { type, name, value } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
console.log(value); // undefined

這段代碼額外定義了一個(gè)局部變量value狡逢,然后嘗試為它賦值宁舰,然而在node對(duì)象上,沒(méi)有對(duì)應(yīng)名稱的屬性值奢浑,所以像預(yù)期中的那樣將它賦值為undefined

當(dāng)指定的屬性不存在時(shí)蛮艰,可以隨意定義一個(gè)默認(rèn)值,在屬性名稱后添加一個(gè)等號(hào)(=)和相應(yīng)的默認(rèn)值即可

let node = {
    type: "Identifier",
    name: "foo"
};
let { type, name, value = true } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
console.log(value); // true

在此示例中雀彼,為變量value設(shè)置了默認(rèn)值true壤蚜,只有當(dāng)node上沒(méi)有該屬性或者該屬性值為undefined時(shí)該值才生效。此處沒(méi)有node.value屬性徊哑,因?yàn)関alue使用了預(yù)設(shè)的默認(rèn)值

【為非同名局部變量賦值】

如果希望使用不同命名的局部變量來(lái)存儲(chǔ)對(duì)象屬性的值袜刷,ES6中的一個(gè)擴(kuò)展語(yǔ)法可以滿足需求,這個(gè)語(yǔ)法與完整的對(duì)象字面量屬性初始化程序的很像

let node = {
    type: "Identifier",
    name: "foo"
};
let { type: localType, name: localName } = node;
console.log(localType); // "Identifier"
console.log(localName); // "foo"

這段代碼使用了解構(gòu)賦值來(lái)聲明變量localType和localName莺丑,這兩個(gè)變量分別包含node.type和node.name屬性的值著蟹。type:localType語(yǔ)法的含義是讀取名為type的屬性并將其值存儲(chǔ)在變量localType中,這種語(yǔ)法實(shí)際上與傳統(tǒng)對(duì)象字面量的語(yǔ)法相悖梢莽,原來(lái)的語(yǔ)法名稱在冒號(hào)左邊萧豆,值在右邊;現(xiàn)在值在冒號(hào)右邊昏名,而對(duì)象的屬性名在左邊

當(dāng)使用其他變量名進(jìn)行賦值時(shí)也可以添加默認(rèn)值涮雷,只需在變量名后添加等號(hào)和默認(rèn)值即可

let node = {
    type: "Identifier"
};
let { type: localType, name: localName = "bar" } = node;
console.log(localType); // "Identifier"
console.log(localName); // "bar"

在這段代碼中,由于node.name屬性不存在轻局,變量被默認(rèn)賦值為"bar"

【嵌套對(duì)象解構(gòu)】

解構(gòu)嵌套對(duì)象仍然與對(duì)象字面量的語(yǔ)法相似洪鸭,可以將對(duì)象拆解以獲取想要的信息

let node = {
    type: "Identifier",
    name: "foo",
    loc: {
        start: {
            line: 1,
            column: 1
        },
    end: {
        line: 1,
        column: 4
    }
}
};
let { loc: { start }} = node;
console.log(start.line); // 1
console.log(start.column); // 1

在這個(gè)示例中样刷,我們?cè)诮鈽?gòu)模式中使用了花括號(hào),其含義為在找到node對(duì)象中的loc屬性后览爵,應(yīng)當(dāng)深入一層繼續(xù)查找start屬性置鼻。在上面的解構(gòu)示例中,所有冒號(hào)前的標(biāo)識(shí)符都代表在對(duì)象中的檢索位置拾枣,其右側(cè)為被賦值的變量名沃疮;如果冒號(hào)后是花括號(hào)盒让,則意味著要賦予的最終值嵌套在對(duì)象內(nèi)部更深的層級(jí)中

更進(jìn)一步梅肤,也可以使用一個(gè)與對(duì)象屬性名不同的局部變量名

let node = {
    type: "Identifier",
    name: "foo",
    loc: {
        start: {
            line: 1,
            column: 1
        },
        end: {
            line: 1,
            column: 4
        }
    }
};
// 提取 node.loc.start
let { loc: { start: localStart }} = node;
console.log(localStart.line); // 1
console.log(localStart.column); // 1

在這個(gè)版本中,node.loc.start被存儲(chǔ)在了新的局部變量localStart中邑茄。解構(gòu)模式可以應(yīng)用于任意層級(jí)深度的對(duì)象姨蝴,且每一層都具備同等的功能

數(shù)組解構(gòu)

與對(duì)象解構(gòu)的語(yǔ)法相比,數(shù)組解構(gòu)就簡(jiǎn)單多了肺缕,它使用的是數(shù)組字面量左医,且解構(gòu)操作全部在數(shù)組內(nèi)完成,而不是像對(duì)象字面量語(yǔ)法一樣使用對(duì)象的命名屬性

let colors = [ "red", "green", "blue" ];
let [ firstColor, secondColor ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"

在這段代碼中同木,我們從colors數(shù)組中解構(gòu)出了"red"和"green"這兩個(gè)值浮梢,并分別存儲(chǔ)在變量firstColor和變量secondColor中。在數(shù)組解構(gòu)語(yǔ)法中彤路,我們通過(guò)值在數(shù)組中的位置進(jìn)行選取秕硝,且可以將其存儲(chǔ)在任意變量中,未顯式聲明的元素都會(huì)直接被忽略

在解構(gòu)模式中洲尊,也可以直接省略元素远豺,只為感興趣的元素提供變量名

let colors = [ "red", "green", "blue" ];
let [ , , thirdColor ] = colors;
console.log(thirdColor); // "blue"

這段代碼使用解構(gòu)賦值語(yǔ)法從colors中獲取第3個(gè)元素,thirdColor前的逗號(hào)是前方元素的占位符坞嘀,無(wú)論數(shù)組中的元素有多少個(gè)躯护,都可以通過(guò)這種方法提取想要的元素,不需要為每一個(gè)元素都指定變量名

【解構(gòu)賦值】

數(shù)組解構(gòu)也可用于賦值上下文丽涩,但不需要用小括號(hào)包裹表達(dá)式棺滞,這一點(diǎn)與對(duì)象解構(gòu)不同

let colors = [ "red", "green", "blue" ],
firstColor = "black",
secondColor = "purple";
[ firstColor, secondColor ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"

這段代碼中的解構(gòu)賦值與上一個(gè)數(shù)組解構(gòu)示例相差無(wú)幾,唯一的區(qū)別是此處的firstColor變量和secondColor變量已經(jīng)被定義了

【變量交換】

數(shù)組解構(gòu)語(yǔ)法還有一個(gè)獨(dú)特的用例:交換兩個(gè)變量的值矢渊。在排序算法中继准,值交換是一個(gè)非常常見(jiàn)的操作,如果要在ES5中交換兩個(gè)變量的值昆淡,則須引入第三個(gè)臨時(shí)變量

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

let a = 1,
  b = 2,
  tmp;
tmp = a;
a = b;
b = tmp;
console.log(a); // 2
console.log(b); // 1

在這種變量交換的方式中锰瘸,中間變量tmp不可或缺。如果使用數(shù)組解構(gòu)賦值語(yǔ)法昂灵,就不再需要額外的變量了

// 在 ES6 中互換值
let a = 1,
    b = 2;
[ a, b ] = [ b, a ];
console.log(a); // 2
console.log(b); // 1

在這個(gè)示例中避凝,數(shù)組解構(gòu)賦值看起來(lái)像是一個(gè)鏡像:賦值語(yǔ)句左側(cè)(也就是等號(hào)左側(cè))與其他數(shù)組解構(gòu)示例一樣舞萄,是一個(gè)解構(gòu)模式;右側(cè)是一個(gè)為交換過(guò)程創(chuàng)建的臨時(shí)數(shù)組字面量管削。代碼執(zhí)行過(guò)程中倒脓,先解構(gòu)臨時(shí)數(shù)組,將b和a的值復(fù)制到左側(cè)數(shù)組的前兩個(gè)位置含思,最終結(jié)果是變量互換了它們的值

[注意]如果右側(cè)數(shù)組解構(gòu)賦值表達(dá)式的值為null或undefined崎弃,則會(huì)導(dǎo)致程序拋出錯(cuò)誤

【默認(rèn)值】

也可以在數(shù)組解構(gòu)賦值表達(dá)式中為數(shù)組中的任意位置添加默認(rèn)值,當(dāng)指定位置的屬性不存在或其值為undefined時(shí)使用默認(rèn)值

let colors = [ "red" ];
let [ firstColor, secondColor = "green" ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"

在這段代碼中含潘,colors數(shù)組中只有一個(gè)元素饲做,secondColor沒(méi)有對(duì)應(yīng)的匹配值,但是它有一個(gè)默認(rèn)值"green"遏弱,所以最終secondColor的輸出結(jié)果不會(huì)是undefined

【嵌套數(shù)組解構(gòu)】

嵌套數(shù)組解構(gòu)與嵌套對(duì)象解構(gòu)的語(yǔ)法類似盆均,在原有的數(shù)組模式中插入另一個(gè)數(shù)組模式,即可將解構(gòu)過(guò)程深入到下一個(gè)層級(jí)

let colors = [ "red", [ "green", "lightgreen" ], "blue" ]; // 隨后
let [ firstColor, [ secondColor ] ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"

在此示例中漱逸,變量secondColor引用的是colors數(shù)組中的值"green"泪姨,該元素包含在數(shù)組內(nèi)部的另一個(gè)數(shù)組中,所以seconColor兩側(cè)的方括號(hào)是一個(gè)必要的解構(gòu)模式饰抒。同樣肮砾,在數(shù)組中也可以無(wú)限深入去解構(gòu),就像在對(duì)象中一樣

【不定元素】

函數(shù)具有不定參數(shù)袋坑,而在數(shù)組解構(gòu)語(yǔ)法中有一個(gè)相似的概念——不定元素仗处。在數(shù)組中,可以通過(guò)...語(yǔ)法將數(shù)組中的其余元素賦值給一個(gè)特定的變量

let colors = [ "red", "green", "blue" ];
let [ firstColor, ...restColors ] = colors;
console.log(firstColor); // "red"
console.log(restColors.length); // 2
console.log(restColors[0]); // "green"
console.log(restColors[1]); // "blue"

數(shù)組colors中的第一個(gè)元素被賦值給了firstColor咒彤,其余的元素被賦值給restColors數(shù)組疆柔,所以restColors中包含兩個(gè)元素:"green"和"blue"。不定元素語(yǔ)法有助于從數(shù)組中提取特定元素并保證其余元素可用

【數(shù)組復(fù)制】

在ES5中镶柱,開(kāi)發(fā)者們經(jīng)常使用concat()方法來(lái)克隆數(shù)組

// 在 ES5 中克隆數(shù)組
var colors = [ "red", "green", "blue" ]; var clonedColors = colors.concat();
console.log(clonedColors); //"[red,green,blue]

concat()方法的設(shè)計(jì)初衷是連接兩個(gè)數(shù)組旷档,如果調(diào)用時(shí)不傳遞參數(shù)就會(huì)返回當(dāng)前函數(shù)的副本

在ES6中,可以通過(guò)不定元素的語(yǔ)法來(lái)實(shí)現(xiàn)相同的目標(biāo)

// 在 ES6 中克隆數(shù)組
let colors = [ "red", "green", "blue" ];
let [ ...clonedColors ] = colors;
console.log(clonedColors); //"[red,green,blue]

在這個(gè)示例中歇拆,我們通過(guò)不定元素的語(yǔ)法將colors數(shù)組中的值復(fù)制到clonedColors數(shù)組中

[注意]在被解構(gòu)的數(shù)組中鞋屈,不定元素必須為最后一個(gè)條目,在后面繼續(xù)添加逗號(hào)會(huì)導(dǎo)致程序拋出語(yǔ)法錯(cuò)誤

混合解構(gòu)

可以混合使用對(duì)象解構(gòu)和數(shù)組解構(gòu)來(lái)創(chuàng)建更多復(fù)雜的表達(dá)式故觅,如此一來(lái)厂庇,可以從任何混雜著對(duì)象和數(shù)組的數(shù)據(jù)解構(gòu)中提取想要的信息

let node = {
    type: "Identifier",
    name: "foo",
    loc: {
        start: {
            line: 1,
            column: 1 },
        end: {
            line: 1,
            column: 4 }
    },
    range: [0, 3]
};
let {
    loc: { start },
    range: [ startIndex ]
} = node;
console.log(start.line); // 1
console.log(start.column); // 1
console.log(startIndex); // 0

這段代碼分別將node.loc.start和node.range[0]提取到變量start和startlndex中

解構(gòu)模式中的loc和range僅代表它們?cè)趎ode對(duì)象中所處的位置(也就是該對(duì)象的屬性)。當(dāng)使用混合解構(gòu)的語(yǔ)法時(shí)输吏,則可以從node提取任意想要的信息权旷。這種方法極為有效,尤其是從JSON配置中提取信息時(shí)贯溅,不再需要遍歷整個(gè)結(jié)構(gòu)了

【解構(gòu)參數(shù)】

解構(gòu)可以用在函數(shù)參數(shù)的傳遞過(guò)程中拄氯,這種使用方式更特別躲查。當(dāng)定義一個(gè)接受大量可選參數(shù)的JS函數(shù)時(shí),通常會(huì)創(chuàng)建一個(gè)可選對(duì)象译柏,將額外的參數(shù)定義為這個(gè)對(duì)象的屬性

// options 上的屬性表示附加參數(shù)
function setCookie(name, value, options) {
    options = options || {};
    let secure = options.secure,
        path = options.path,
        domain = options.domain,
        expires = options.expires; // 設(shè)置 cookie 的代碼
} // 第三個(gè)參數(shù)映射到 options
setCookie("type", "js", {
    secure: true,
    expires: 60000 });

許多JS庫(kù)中都有類似的setCookie()函數(shù)镣煮,而在示例函數(shù)中,name和value是必需參數(shù)鄙麦,而secure典唇、path、domain和expires則不然胯府,這些參數(shù)相對(duì)而言沒(méi)有優(yōu)先級(jí)順序介衔,將它們列為額外的命名參數(shù)也不合適,此時(shí)為options對(duì)象設(shè)置同名的命名屬性是一個(gè)很好的選擇∶私伲現(xiàn)在的問(wèn)題是夜牡,僅查看函數(shù)的聲明部分,無(wú)法辨識(shí)函數(shù)的預(yù)期參數(shù)侣签,必須通過(guò)閱讀函數(shù)體才可以確定所有參數(shù)的情況

如果將options定義為解構(gòu)參數(shù),則可以更清晰地了解函數(shù)預(yù)期傳入的參數(shù)急迂。解構(gòu)參數(shù)需要使用對(duì)象或數(shù)組解構(gòu)模式代替命名參數(shù)

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">function setCookie(name, value, { secure, path, domain, expires }) { // 設(shè)置 cookie 的代碼
}
setCookie("type", "js", {
secure: true,
expires: 60000 });</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

這個(gè)函數(shù)與之前示例中的函數(shù)具有相似的特性影所,只是現(xiàn)在使用解構(gòu)語(yǔ)法代替了第3個(gè)參數(shù)來(lái)提取必要的信息,其他參數(shù)保持不變僚碎,但是對(duì)于調(diào)用setCookie()函數(shù)的使用者而言猴娩,解構(gòu)參數(shù)變得更清晰了

【必須傳值的解構(gòu)參數(shù)】

解構(gòu)參數(shù)有一個(gè)奇怪的地方,默認(rèn)情況下勺阐,如果調(diào)用函數(shù)時(shí)不提供被解構(gòu)的參數(shù)會(huì)導(dǎo)致程序拋出錯(cuò)誤

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">// 出錯(cuò)卷中!
setCookie("type", "js");</pre>

缺失的第3個(gè)參數(shù),其值為undefined渊抽,而解構(gòu)參數(shù)只是將解構(gòu)聲明應(yīng)用在函數(shù)參數(shù)的一個(gè)簡(jiǎn)寫(xiě)方法蟆豫,其會(huì)導(dǎo)致程序拋出錯(cuò)誤。當(dāng)調(diào)用setCookie()函數(shù)時(shí)懒闷,JS引擎實(shí)際上做了以下這些事情

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">function setCookie(name, value, options) {
let { secure, path, domain, expires } = options; // 設(shè)置 cookie 的代碼
}</pre>

如果解構(gòu)賦值表達(dá)式的右值為null或undefined十减,則程序會(huì)報(bào)錯(cuò)。同理愤估,若調(diào)用setCookie()函數(shù)時(shí)不傳入第3個(gè)參數(shù)帮辟,也會(huì)導(dǎo)致程序拋出錯(cuò)誤

如果解構(gòu)參數(shù)是必需的,大可忽略掉這些問(wèn)題玩焰;但如果希望將解構(gòu)參數(shù)定義為可選的由驹,那么就必須為其提供默認(rèn)值來(lái)解決這個(gè)問(wèn)題

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">function setCookie(name, value, { secure, path, domain, expires } = {}) { // ...
}</pre>

這個(gè)示例中為解構(gòu)參數(shù)添加了一個(gè)新對(duì)象作為默認(rèn)值,secure昔园、path蔓榄、domain及expires這些變量的值全部為undefined闹炉,這樣即使在調(diào)用setCookie()時(shí)未傳遞第3個(gè)參數(shù),程序也不會(huì)報(bào)錯(cuò)

【默認(rèn)值】

可以為解構(gòu)參數(shù)指定默認(rèn)值润樱,就像在解構(gòu)賦值語(yǔ)句中那樣渣触,只需在參數(shù)后添加等號(hào)并且指定一個(gè)默認(rèn)值即可

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">function setCookie(name, value,
{
secure = false,
path = "/",
domain = "example.com",
expires = new Date(Date.now() + 360000000)
} = {}
) { // ...
}</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

在這段代碼中,解構(gòu)參數(shù)的每一個(gè)屬性都有默認(rèn)值壹若,從而無(wú)須再逐一檢查每一個(gè)屬性是否都有默認(rèn)值嗅钻。然而,這種方法也有很多缺點(diǎn)店展。首先养篓,函數(shù)聲明變得比以前復(fù)雜了;其次赂蕴,如果解構(gòu)參數(shù)是可選的柳弄,那么仍然要給它添加一個(gè)空對(duì)象作為參數(shù),否則像setCookie("type","js")這樣的調(diào)用會(huì)導(dǎo)致程序拋出錯(cuò)誤

對(duì)于對(duì)象類型的解構(gòu)參數(shù)概说,最好為其賦予相同解構(gòu)的默認(rèn)參數(shù)

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">function setCookie(name, value,
{
secure = false,
path = "/",
domain = "example.com",
expires = new Date(Date.now() + 360000000)
} = {
secure : false,
path : "/",
domain : "example.com",
expires : new Date(Date.now() + 360000000)
}
) { // ...
}</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

現(xiàn)在函數(shù)變得更加完整了碧注,第一個(gè)對(duì)象字面量是解構(gòu)參數(shù),第二個(gè)為默認(rèn)值糖赔。但是這會(huì)造成非常多的代碼冗余萍丐,可以將默認(rèn)值提取到一個(gè)獨(dú)立對(duì)象中,并且使用該對(duì)象作為解構(gòu)和默認(rèn)參數(shù)的一部分放典,從而消除這些冗余

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">const setCookieDefaults = {
secure : false,
path : "/",
domain : "example.com",
expires : new Date(Date.now() + 360000000)
} function setCookie(name, value,{
secure = setCookieDefaults.secure,
path = setCookieDefaults.path,
domain = setCookieDefaults.domain,
expires = setCookieDefaults.expires
}=setCookieDefaults) { // ...
}</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

在這段代碼中逝变,默認(rèn)值已經(jīng)被放到setCookieDefaults對(duì)象中,除了作為默認(rèn)參數(shù)值外奋构,在解構(gòu)參數(shù)中可以直接使用這個(gè)對(duì)象來(lái)為每一個(gè)綁定設(shè)置默認(rèn)參數(shù)壳影。使用解構(gòu)參數(shù)后,不得不面對(duì)處理默認(rèn)參數(shù)的復(fù)雜邏輯弥臼,但它也有好的一面宴咧,如果要改變默認(rèn)值,可以立即在setCookieDefaults中修改醋火,改變的數(shù)據(jù)將自動(dòng)同步到所有出現(xiàn)過(guò)的地方

其他解構(gòu)

【字符串解構(gòu)】

字符串也可以解構(gòu)賦值悠汽。這是因?yàn)椋址晦D(zhuǎn)換成了一個(gè)類似數(shù)組的對(duì)象

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">const [a, b, c, d, e] = 'hello';
console.log(a);//"h"
console.log(b);//"e"
console.log(c);//"l"
console.log(d);//"l"
console.log(e);//"o"</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

類似數(shù)組的對(duì)象都有一個(gè)length屬性芥驳,因此還可以對(duì)這個(gè)屬性解構(gòu)賦值

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">const {length} = 'hello';
console.log(length);//5</pre>

【數(shù)值和布爾值解構(gòu)】

解構(gòu)賦值時(shí)柿冲,如果等號(hào)右邊是數(shù)值和布爾值,則會(huì)先轉(zhuǎn)為對(duì)象

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">let {toString:s1} = 123;
console.log(s1 === Number.prototype.toString);//true
let {toString:s2} = true;
console.log(s2 === Boolean.prototype.toString);//true</pre>

解構(gòu)賦值的規(guī)則是兆旬,只要等號(hào)右邊的值不是對(duì)象或數(shù)組假抄,就先將其轉(zhuǎn)為對(duì)象。由于undefinednull無(wú)法轉(zhuǎn)為對(duì)象,所以對(duì)它們進(jìn)行解構(gòu)賦值宿饱,都會(huì)報(bào)錯(cuò)

<pre style="margin: 0px; white-space: pre-wrap; word-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError</pre>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末熏瞄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谬以,更是在濱河造成了極大的恐慌强饮,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件为黎,死亡現(xiàn)場(chǎng)離奇詭異邮丰,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)铭乾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)剪廉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人斗蒋,你說(shuō)我怎么就攤上這事〉阎剩” “怎么了泉沾?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)经瓷。 經(jīng)常有香客問(wèn)我爆哑,道長(zhǎng),這世上最難降的妖魔是什么舆吮? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮队贱,結(jié)果婚禮上色冀,老公的妹妹穿的比我還像新娘。我一直安慰自己柱嫌,他們只是感情好锋恬,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著编丘,像睡著了一般与学。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘉抓,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天索守,我揣著相機(jī)與錄音,去河邊找鬼抑片。 笑死卵佛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播截汪,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼疾牲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了衙解?” 一聲冷哼從身側(cè)響起阳柔,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚓峦,沒(méi)想到半個(gè)月后舌剂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡枫匾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年架诞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片干茉。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谴忧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出角虫,到底是詐尸還是另有隱情沾谓,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布戳鹅,位于F島的核電站均驶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏枫虏。R本人自食惡果不足惜妇穴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望隶债。 院中可真熱鬧腾它,春花似錦、人聲如沸死讹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赞警。三九已至妓忍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愧旦,已是汗流浹背世剖。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工友存, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留健爬,地道東北人豪嗽。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像俭嘁,于是被迫代替她去往敵國(guó)和親庆尘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子撑教,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344