ES6賦值—解構(gòu)賦值

作者:米書林
參考文章:《菜鳥教程》椅贱、《 ECMAScript 6 入門》(阮一峰)

解構(gòu)的定義

????ES6 允許按照一定模式,從數(shù)組和對象中提取值只冻,對變量進(jìn)行賦值庇麦,這被稱為解構(gòu)。

結(jié)構(gòu)表達(dá)式的組成

1.解構(gòu)的源:解構(gòu)表達(dá)式值的來源喜德,表達(dá)式的右邊部分
2.解構(gòu)的目標(biāo):定義解構(gòu)表達(dá)式值的存儲變量山橄,表達(dá)式的左邊部分

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

基本用法
let [a,b,c] = [1,2,3];
console.log(a);  \\ 1
console.log(b);  \\ 2
console.log(c);  \\ 3

????只要表達(dá)式左右的結(jié)構(gòu)一樣,左邊對應(yīng)的變量能在右邊找到對應(yīng)的值住诸,就能將右邊的值賦值給左邊的變量驾胆。
????我們可以用解構(gòu)賦值來簡化后臺給我們傳遞的數(shù)據(jù),減少數(shù)據(jù)遍歷的循環(huán)次數(shù)

可嵌套
let [a, [[b], c]] = [1, [[2], 3]];
// a = 1
// b = 2
// c = 3

若上述變量b不用[]括起來贱呐,則b返回的值帶有中括號丧诺,如下:

let [a, [b, c]] = [1, [[2], 3]];
// a = 1
// b = [2]
// c = 3
可忽略
let [a, , b] = [1, 2, 3];
// a = 1
// b = 3

若被忽略項在末尾,直接忽略奄薇;若被忽略項不在末尾驳阎,則需要用","來填補(bǔ),若省略",",則瀏覽器默認(rèn)會在末尾補(bǔ)齊
例如:

let [a, , b] = [1, 2, 3, 4];
// a = 1
// b = 3

let [a, , , b] = [1, 2, 3, 4];
// a = 1
// b = 4
不完全解構(gòu)
let [a = 1, b] = []; 
// a = 1
// b = undefined

若定義的變量在右側(cè)無對應(yīng)項呵晚,則會被賦值為:undefined;
若定義的變量給定默認(rèn)值蜘腌,且匹配結(jié)果為undefined,則解構(gòu)的結(jié)果為默認(rèn)值。

剩余運(yùn)算符
let [a, ...b] = [1, 2, 3];
//a = 1
//b = [2, 3]

注意:含有剩余運(yùn)算符項表達(dá)式要放在最后一項

結(jié)構(gòu)源為字符串
let [a,b,c] = "ES6"
// a = "E"
// b = "S"
// c = "6"
解構(gòu)默認(rèn)值

????當(dāng)解構(gòu)模式有匹配結(jié)果饵隙,且匹配結(jié)果是 undefined 時撮珠,會觸發(fā)默認(rèn)值作為返回結(jié)果。

let [a = 3, b = a] = [undefined];     // a = 3, b = 3
let [a = 3, b = a] = [1];    // a = 1, b = 1
let [a = 3, b = a] = [1, 2]; // a = 1, b = 2

分析:
????第一個表達(dá)式a匹配的結(jié)果為undefined,故返回a的默認(rèn)值金矛,a的默認(rèn)值為3芯急,b匹配的結(jié)果為undefined,故返回b的默認(rèn)值,b的默認(rèn)值為b=a,a此時為3驶俊,故b為3娶耍;
????第二個表達(dá)式a匹配的結(jié)果為1,故返回a的匹配值1,b匹配的結(jié)果為undefined,故返回b的默認(rèn)值饼酿,b的默認(rèn)值為b=a,a此時為1榕酒,故b為1;
????第三個表達(dá)式a匹配的結(jié)果為1,故返回a的匹配值1故俐,b匹配的結(jié)果為2,故返回b的匹配值2想鹰;

解構(gòu)匹配值為null
let [a=12] = [null]
// a = null
解構(gòu)Set結(jié)構(gòu)
let [a, c, c] = new Set(['a', 'b', 'c']);
//  a = "a"
//  b = "b"
//  c = "c"

不只是數(shù)組,只要能遍歷的結(jié)構(gòu)都能使用解構(gòu)
不能遍歷的結(jié)構(gòu)不能被解構(gòu)购披,例如:

let [a] = 1;
let [a] = false;
let [a] = NaN;
let [a] = undefined;
let [a] = null;
let [a] = {};

以上代碼瀏覽器執(zhí)行后都會報錯杖挣。

對象模型的解構(gòu)

基本
let {name,age} = {name:"張三",age:20}
// name = "張三"
// age = 20

注意:此處等號左側(cè)的變量name是name:name縮寫,age是age:age的縮寫刚陡,ES6新特性規(guī)定對象的屬性和值用同一變量可以簡寫為一個惩妇。因此:結(jié)構(gòu)后的結(jié)果實際上是賦值給了對象屬性值的變量

對象屬性值的解構(gòu)
let {name:name1} = {name:"李四"}
// name = undefined(瀏覽器報錯:name is not defined)
// name1 = "李四"

上面代碼可以看出解構(gòu)的結(jié)果賦值給了對象屬性值對應(yīng)的變量

可嵌套
let {p: [x, { y }] } = {p: ['hello', {y: 'world'}] };
// x = 'hello'
// y = 'world'
可忽略
let {p: [x, {  }] } = {p: ['hello', {y: 'world'}] };
// x = 'hello'
let {p: [, { y }] } = {p: ['hello', {y: 'world'}] };
// y = 'world'
不完全解構(gòu)
let {p: [{ y }, x ] } ={p: [{y: 'world'}] };
// x = undefined
// y = 'world'
剩余運(yùn)算符
let {a, b, ...rest } = {a: "張三", b: "李四", c: "王五", d: "李二"};
// a =  "張三"
// b = "李四"
// rest = {c: "王五", d: "李二"}
解構(gòu)默認(rèn)值
let {a = 1, b = 2} = {a: 3};
// a = 3; b = 2;
let {a: aa = 10, b: bb = 5} = {a: 3};
// aa = 3; bb = 5; 

默認(rèn)解構(gòu)值在匹配結(jié)果為undefined時觸發(fā)。

已經(jīng)聲明的變量用于解構(gòu)賦值

// 錯誤的寫法
let x;
{x} = {x: 1};
// Uncaught SyntaxError: Unexpected token '='

以上代碼瀏覽器會報錯筐乳,原因是瀏覽器將大括號解析成了代碼塊歌殃,兩個代碼塊之間要么為空格,要么為“;”,故此處報錯蝙云。解決的辦法是用()將它轉(zhuǎn)換成一個表達(dá)式

let x;
({x} = {x: 1});

應(yīng)用場景

1.任意個參數(shù)求和

傳統(tǒng)方法:
????js傳統(tǒng)方法需要借助arguments來實現(xiàn)氓皱,具體方法如下:

function sum(){
  var sum = 0;
  var len = arguments.length; // 將長度存儲在變量中可以減少循環(huán)次數(shù),提升性能
  for(var i = 0;i < len;i++){
    sum +=arguments[i]
  }
  return sum;
}
sum(1,2,3);  // 6
sum(1,2,"4"); // "34"

此處只是為了對比傳統(tǒng)方法和ES6新方法求和勃刨,未作數(shù)值類型轉(zhuǎn)化波材,故第二個調(diào)用出現(xiàn)了字符串拼接

ES6新方法:
????ES6用剩余項表達(dá)式和解構(gòu)來存儲參數(shù)個數(shù),求和的方法如下:

function sum(...nums){
  let sum = nums.reduce((x,y)=>{return x+y})
  return sum
}
sum(1,2,3);  // 6
sum(1,2,"4"); // "34"

注意此處使用了ES6數(shù)組的新方法:reduce身隐,reduce的作用是匯總廷区,輸入一堆,輸出一個結(jié)果
????在這里我們可能感覺兩種方法的實現(xiàn)原理好像是一樣的額贾铝,其實并不然隙轻,傳統(tǒng)方法借助的arguments是一個類數(shù)組埠帕,雖然我們可以像數(shù)組一樣用下標(biāo),即arguments[0],arguments[1],...的方式去訪問它玖绿,也能通過arguments.length來計算傳入?yún)?shù)的個數(shù)敛瓷,還能使用arguments.callee(注意在ES5中這個屬性已被廢棄,caller不是的屬性)斑匪,然而它還是沒有數(shù)組常用的一些方法呐籽,比如reduce,pop,push,shift,unshift等,所以用傳統(tǒng)方法求參數(shù)和要比ES6的代碼多好幾行秤标。

2.不借助第三個參數(shù)交換變量的值

傳統(tǒng)方法:
????傳統(tǒng)方法(ES6之前绝淡,C語言等)要交換兩個變量的值需要借助第三個變量,在js中的實現(xiàn)方法大概如下:

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

所以苍姜,傳統(tǒng)方法大概需要5行代碼才能實現(xiàn)。

ES6方法:
ES6中我們不需要借助第三個參數(shù)悬包,具體實現(xiàn)方法如下:

let a = 1;
let b = 2;
[a, b] = [b, a];
// a = 2;
// b = 1;

從上面可以看出我們只需要三行代碼就能完成參數(shù)的交換衙猪。

3.收集函數(shù)的剩余參數(shù),用作公共函數(shù)可選項

????我們都知道js中傳遞的實參可以不和形參一一對應(yīng);
????形參個數(shù)大于實參個數(shù)時布近,多余的形參會被初始化為undefined(函數(shù)聲明整體提升垫释,隨后找形參并將形參初始化為undefined,最后才是實參和形參相統(tǒng)一撑瞧,所以沒有實參對應(yīng)的形參值仍然是undefined)棵譬;
????當(dāng)形參個數(shù)小于實參個數(shù)時,多余的實參會被忽略预伺;
????因此订咸,一些場景下即使我們只用到一次的或者可能不會用到的參數(shù)都要在定義形參來傳遞,一些參數(shù)個數(shù)不確定的場景下我們只能通過多定義形參來解決問題酬诀,但是這顯然有些笨拙脏嚷。
????在ES6新特性中,我們可以通過“...+變量名”來解決參數(shù)傳遞的問題瞒御。
????下面我們可以通過函數(shù)來簡單模范api的可選參數(shù)父叙,我們把必填參數(shù)放在前面,把可選參數(shù)放在剩余項里肴裙,這樣我們的代碼如下:

function dateFormat(a,..b){
  ...
}

????上面代碼a是必填參數(shù)趾唱,b是可選參數(shù)的集合,這樣我們就能通過一個變量將不常用的參數(shù)放到一個集合中了蜻懦。

4.返回多個函數(shù)結(jié)果

????ES6之前我們想從函數(shù)返回多個結(jié)果甜癞,只能將它們放在數(shù)組或?qū)ο罄锓祷兀胍@取每一個返回結(jié)果阻肩,少不了循環(huán)和遍歷語句带欢,這很讓人頭疼运授。
????有了ES6后我們就可以將函數(shù)執(zhí)行的結(jié)果一個一個的提取出來。大概的代碼如下:

// 返回一個數(shù)組
function test() {
  return [1, 2, 3];
}
let [a, b, c] = test();

// 返回一個對象
function test() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = test();
5.簡化底層數(shù)據(jù)的調(diào)用

????很多時候后臺返回給我們的都是一些對象和數(shù)組的混合嵌套體乔煞,對于深層數(shù)據(jù)的訪問我們往往需要寫一長串“.”引用吁朦,用解構(gòu)賦值我們就可以將這些數(shù)據(jù)單獨(dú)獲取出來。

6.設(shè)置函數(shù)參數(shù)的默認(rèn)值
jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
} = {}) {
  // ... do stuff
};

指定參數(shù)的默認(rèn)值渡贾,就避免了在函數(shù)體內(nèi)部再寫var foo = config.foo || 'default foo';這樣的語句逗宜。

7.遍歷 Map 結(jié)構(gòu)

任何部署了 Iterator 接口的對象,都可以用for...of循環(huán)遍歷空骚。Map 結(jié)構(gòu)原生支持 Iterator 接口纺讲,配合變量的解構(gòu)賦值,獲取鍵名和鍵值就非常方便囤屹。

const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
console.log(key + " is " + value);
}
// first is hello
// second is world

如果只想獲取鍵名熬甚,或者只想獲取鍵值,可以寫成下面這樣肋坚。

// 獲取鍵名
for (let [key] of map) {
  // ...
}

// 獲取鍵值
for (let [,value] of map) {
  // ...
}
8.輸入模塊的指定方法

加載模塊時乡括,往往需要指定輸入哪些方法。解構(gòu)賦值使得輸入語句非常清晰智厌。

const { SourceMapConsumer, SourceNode } = require("source-map");

注:此文參考了菜鳥教程阮一峰博文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诲泌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子铣鹏,更是在濱河造成了極大的恐慌敷扫,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诚卸,死亡現(xiàn)場離奇詭異葵第,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)惨险,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門羹幸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辫愉,你說我怎么就攤上這事栅受。” “怎么了恭朗?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵屏镊,是天一觀的道長。 經(jīng)常有香客問我痰腮,道長而芥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任膀值,我火速辦了婚禮棍丐,結(jié)果婚禮上误辑,老公的妹妹穿的比我還像新娘。我一直安慰自己歌逢,他們只是感情好巾钉,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秘案,像睡著了一般砰苍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上阱高,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天赚导,我揣著相機(jī)與錄音,去河邊找鬼赤惊。 笑死吼旧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的未舟。 我是一名探鬼主播黍少,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼处面!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起菩掏,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤魂角,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后智绸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體野揪,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年瞧栗,在試婚紗的時候發(fā)現(xiàn)自己被綠了斯稳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡迹恐,死狀恐怖挣惰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情殴边,我是刑警寧澤憎茂,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站锤岸,受9級特大地震影響竖幔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜是偷,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一拳氢、第九天 我趴在偏房一處隱蔽的房頂上張望募逞。 院中可真熱鬧,春花似錦馋评、人聲如沸放接。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽透乾。三九已至,卻和暖如春磕秤,著一層夾襖步出監(jiān)牢的瞬間乳乌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工市咆, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留汉操,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓蒙兰,卻偏偏與公主長得像磷瘤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子搜变,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354