ES6學習-解構

對象和數組字面量是JavaScript中兩種最常用的數據結構,由于JSON數據結構的普及绽诚,兩者已經成為語言中特別重要的一部分拯勉。在編碼過程中,我們經常定義許多對象和數組憔购,然后有組織地從中提取相關的信息片段宫峦。ES6添加了可以簡化這種任務的新特性:解構。

為何使用解構功能

在ES5中玫鸟,開發(fā)者為了從對象和數組中獲取特定數據并賦值給變量导绷,編寫了很多同質化代碼。

let options={
    repeat: true,
    save: false
};
//從對象中提取數據
let repeat=options.repeat,
    save=options.save;

這段代碼中從options中提取repeat和save的值并存儲的過程十分相似屎飘,如果需要得到的值很多妥曲,則會編寫很多次同質化代碼贾费,如果代碼中海油嵌套結構,則會非常麻煩檐盟。
所以ES6為對象和數組都添加了結構功能褂萧,將數據結構打散過稱變得很簡單,使我們更容易獲取信息葵萎。

對象解構

對象字面量的語法形式是在一個賦值操作符左邊放置一個對象字面量导犹。

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

在這段代碼中,node.type的值存儲在名為type的變量中羡忘;node.name的值存儲在名為name的變量中谎痢。
值得注意的是:如果用var、let和const解構聲明變量卷雕,則必須要為其初始化节猿,否則報錯。

//語法錯誤
var {type,name};
//語法錯誤
let {type,name};
//語法錯誤
const {type,name};
解構賦值

我們同樣可以在給變量賦值時使用解構語法漫雕。

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

在示例中滨嘱,聲明type和name時初始化了一個值,在后面通過結構重新賦值浸间。需要注意的地方是:因為開放的{}會被視為代碼塊太雨,而語法規(guī)定,代碼塊不允許出現在賦值語句左邊发框,所以需要加小括號使其轉化為一個表達式躺彬。
結構表達式的值與表達式右側(也就是=右側)的值相等煤墙,如此在任何可以使用值得地方你都可以使用解構賦值表達式梅惯。

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

值得注意的點是:如果右側的值為null或undefined會導致程序拋出錯誤。也就是嘗試讀取null和undefined的屬性的行為都會拋出錯誤仿野。

默認值

如果指定的局部變量名稱在對象中不存在铣减,那么這個局部變量會被賦值undefined。

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

當指定屬性不存在時脚作,可以隨意定義一個默認值葫哗。

let node={
    type:"Indetifier",
    name:"foo"
};
let {type,name,value=true}=node;
console.log(type);//"Indetifier"
console.log(name);//"foo"
console.log(value);//"true"
為非同名局部變量賦值

如果希望用不同命名的局部變量來存儲對象屬性的值,可以這樣寫球涛。

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

這段代碼使用了解構聲明來聲明變量localType和localName劣针,這兩個量分別包含node.type和node.name的值,
當使用其他變量名進行賦值時也可以為其添加默認值亿扁。

let node={
    type: "Identifier",
};
let {type: localType="hahaha",name: localName="ccg"}=node;
console.log(localType);//"Identifier"
console.log(localName);//ccg
嵌套對象解構
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

在這個示例中捺典,我們在解構模式中使用了花括號,其含義是在找到node對象的loc屬性后从祝,深入一層找到start屬性襟己。
更近一步引谜,可以使用一個與對象屬性名不同的局部變量名:

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

對象解構功能很好用,但是值得注意的是擎浴,你可能會創(chuàng)建一個無效表達式员咽,它是合法的,但是什么都干不了贮预。

//未申明任何變量
let {loc:{}}=node;

左邊的loc不是即將創(chuàng)建的綁定贝室,只是代表對象中的檢索屬性的位置。

數組解構

與對象解構的語法相比萌狂,數組解構就簡單多了档玻,它使用的是數組字面量,且解構操作全部在數組內完成茫藏,而不是像對象字面量語法一樣使用對象的命名屬性:

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

在這段代碼中误趴,我們從colors數組中解構出“red”和“green”這兩個值,并分別存儲在變量firstColor和變量secondColor中务傲。在數組解構語法中凉当,我們通過值在數組的位置進行選取,且可以將其存儲在任意變量中售葡,未顯式申明的元素會被忽略哦看杭。值得注意的是,這個過程中數組不會發(fā)生任何變化挟伙。
在解構模式中楼雹,也可以直接省略元素,只為需要的元素提供變量名尖阔。

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

thiirdColor前的逗號是前方元素的占位符贮缅,無論數組元素有多少個,你都可以通過這種方式提取需要的元素介却,并不需要額外指定變量名谴供。
值得注意的是:使用var、let和const聲明數組解構的綁定時齿坷,必須要提供一個初始化程序桂肌。

解構賦值

數組解構也可以用于賦值上下文,但不需要用小括號包裹表達式永淌,這一點與數組解構的約定不同崎场。

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

解構語法中還有一個特例:交換兩個變量的值。

//在es5中交換變量
let a=1,
     b=2,
     tmp;
tmp=a;
a=b;
b=tmp;
console.log(a);//2
console.log(b);//1
//如果使用數組解構賦值語法遂蛀,就不需要用額外的變量了谭跨。
//在ES6中交換變量
let a=1,
     b=2;
[a,b]=[b,a];
console.log(a);//2
console.log(b);//1

代碼執(zhí)行過程中:先解構臨時數組,將b和a的值復制到左側數組的前兩個位置,最終結果是變量互換了它們的值饺蚊。
值得注意的是:如果右側數組解構賦值表達式的值為null或undefined萍诱,則會導致程序 拋出錯誤。

默認值

也可以在數組解構賦值表達式中為數組中的任意位置添加默認值污呼,當指定位置的屬性不存在或其值為undefined時使用默認值:

let colors=["red"];
let [firstColor,secondColor="green"]=colors;
console.log(firstColor);//"red"
console.log(secondColor);//"green"
嵌套數組解構

在原有的數組模式中插入另一個數組模式裕坊,即可將解構過程深入到下一層次:

let colors=["red",["green","lightgreen"],"blue"];
//接下來
let [firstColor,[secondColor]]=colors;
console.log(firstColor);//"red"
console.log(secondColor);//"green"
不定元素

數組解構中也可以用不定元素。

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"
數組復制
//在ES5中克隆數組
var colors=["red","green","blue"];
var clonedColors=colors.concat();//concat()設計初衷是用于連接兩個數組燕酷,當不傳遞 參數時就會返回當前的副本籍凝。
console.log(clonedColors);//
//在ES6中的新方法
let colors=["red","green","blue"];
let [...clonedColors]=colors;
console.log(clonedColors);//"[red,green,blue]"

比較這個方法和concat()方法的可讀性,喜歡用哪個你就用哪個吧苗缩。QAQ...
值得注意的是在被解構的數組中饵蒂,不定元素必須為最后一個條目,在后面添加逗號會報錯酱讶。

混合解構

可以混合使用對象解構和數組解構來創(chuàng)建更多復雜的表達式退盯。

let node={
    type:"Indentifier",
    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
解構參數

解構可以用在函數參數的傳遞過程中,這種特別方式更特別泻肯。當定義接受大量可選參數的JavaScript函數時渊迁,我們通常會創(chuàng)建一個可選對象,將額外的參數定義為這個對象的屬性灶挟。

//options的屬性表示其他參數
function setCookie(name,value,options){
    options=options||{};
    let secrue=options.secrue,
        path=options.path,
        domain=options.domain,
        expires=options.expires;
    //設置cookie的代碼
}
//第三個參數映射到options中
setCookie("type","js",{
    secrue:true,
    expires:60000
});

這樣的setCookie存在的問題是僅查看函數的聲明部分琉朽,無法辨識函數的預期函數,必須閱讀函數體才可以確定所有參數的情況稚铣。
定義為解構函數就可以解決這個問題箱叁。

function setCookie(name,value,{secrue,path,domain,expires}){
    //設置cookie的代碼
}
//第三個參數映射到options中
setCookie("type","js",{
    secrue:true,
    expires:60000
});
必須傳值的解構參數

解構函數有個奇怪的地方,默認情況下惕医,如果調用函數時不提供被解構的參數會導致程序拋出錯誤耕漱。

setCookie("type","js");//程序報錯

缺失的第三個參數,其值為undefined曹锨,而解構參數只是將解構聲明應用到在函數參數的一個寫法孤个,其會導致程序拋出錯誤剃允。當調用setCookie()函數時沛简,JavaScript引擎實際上做了這些事情:

function setCookie(name,value,options){
    let {secure,path,domain,expires}=options;
   //設置cookie的代碼
}

如果解構表達式的右邊為null或undefined,則程序會報錯斥废,同理椒楣,調用時不傳參數也會報錯。
如果希望解構函數參數可選牡肉,可以這樣寫:

function setCookie(name,value,{secure,path,domain,expires}={}){
   //...
}
解構參數的默認值

可以為解構函數指定默認參數值捧灰,就像在解構賦值語句中一樣,只需要添加默認值就好了。

function setCookie(name,value,{
    secure=false,
    path="/",
    domain="example.com",
    expires=new Date(Date.now()+360000000)
}){
    //...
}

這種方法看著挺清晰毛俏,但是函數聲明比以前復雜炭庙,這里建議直接用相同的解構作為默認參數:

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)
}
){
    //...
}

現在函數變得更加完整了,第一個對象字面量是解構參數煌寇,第二個為默認值焕蹄,為了解決部分代碼冗余,可以將默認值封裝在一個獨立對象中阀溶。

const setCookDefaults={
    secure=false,
    path="/",
    domain="example.com",
    expires=new Date(Date.now()+360000000)
};
function setCookie(name,value,{
    secure=false,
    path="/",
    domain="example.com",
    expires=new Date(Date.now()+360000000)
}=setCookieDefaults
){
    //...
}

在這段代碼中腻脏,默認值已經被放到setCookieDefaults對象中,除了作為默認參數值银锻,在解構參數中可以直接使用這個對象為每一個綁定設置默認值永品。使用解構參數后缤骨,不得不處理默認參數的復雜邏輯放祟,但它也有好的一面箍铲,如果要改變默認值竖伯,可以立即在setCookieDefaults中修改师枣,改變的值將自動同步到所有出現過的地方铃慷。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末阅束,一起剝皮案震驚了整個濱河市捺弦,隨后出現的幾起案子殃饿,更是在濱河造成了極大的恐慌谋作,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乎芳,死亡現場離奇詭異遵蚜,居然都是意外死亡,警方通過查閱死者的電腦和手機奈惑,發(fā)現死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門吭净,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肴甸,你說我怎么就攤上這事寂殉。” “怎么了原在?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵友扰,是天一觀的道長。 經常有香客問我庶柿,道長村怪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任浮庐,我火速辦了婚禮甚负,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己梭域,他們只是感情好斑举,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著病涨,像睡著了一般懂昂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上没宾,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天凌彬,我揣著相機與錄音,去河邊找鬼循衰。 笑死铲敛,一個胖子當著我的面吹牛,可吹牛的內容都是我干的会钝。 我是一名探鬼主播伐蒋,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼迁酸!你這毒婦竟也來了先鱼?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤奸鬓,失蹤者是張志新(化名)和其女友劉穎焙畔,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體串远,經...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡宏多,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了澡罚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伸但。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖留搔,靈堂內的尸體忽然破棺而出更胖,到底是詐尸還是另有隱情,我是刑警寧澤隔显,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布却妨,位于F島的核電站,受9級特大地震影響荣月,放射性物質發(fā)生泄漏管呵。R本人自食惡果不足惜梳毙,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一哺窄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦萌业、人聲如沸坷襟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婴程。三九已至,卻和暖如春抱婉,著一層夾襖步出監(jiān)牢的瞬間档叔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工蒸绩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衙四,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓患亿,卻偏偏與公主長得像传蹈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子步藕,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內容