ECMAScript6標準之解構賦值語法及應用

在七種方案解決JavaScript交換兩個變量值的問題中

我寫的最後一種方案就是用到瞭ES6的解構賦值語法

[a, b] = [b, a]

下面我來詳細說明一下什麼是解構賦值

數組解構

基本概念

按照一定模式,從數組和對象中提取,對變量進行賦值,稱為解構

通過解構我們可以讓賦值更優雅便捷

// 一般賦值
var a = 1,
    b = 2,
    c = 3;
//解構賦值
var [a, b, c] = [1, 2, 3];

當然不僅僅是var,let和const也可以

let arr = [1, 2, 3]
const [a, b, c] = arr;

語法本質

實質上這個語法就是一種模式匹配

如果等號兩邊模式相同

左邊變量就會被賦予相應值

所以下面的形式也可以正常賦值

var [a, [b, [c, d]]] = [1, [2, [3, 4]]];
console.log(a, b, c, d);//1 2 3 4

不過我們完全沒有必要寫這麼復雜

特殊用法

解構賦值還可以和展開操作符“…”配合使用

如果展開操作符在等號左邊

那麼就會把剩餘的值合並為一個數組

這個操作符隻能寫在最後一個變量前面

var [left, ...right] = [1, 2, 3, 4, 5];
console.log(left, right);//1 [2,3,4,5]

如果展開操作符在等號右邊

就是把數組展開再賦值

var arr = [2, 3, 4];
var [a, b, c, d] = [1, ...arr];
console.log(a, b, c, d);//1 2 3 4

解構失敗與不完全解構

如果沒有在匹配中沒有對應值,那麼它的值就是undefined

也就是解構失敗

等號右邊少值

var [a, b, c] = [1, 2];
console.log(a, b, c);//1 2 undefined

與它相對的就是不完全解構

等號左邊少值

var [a, b] = [1, 2, 3];
console.log(a, b);//1 2

錯誤解構

如果等號右邊不是數組(不是可遍歷解構) 就會報錯 比如說這些情況是不能賦值解構的

var [foo] = 1/true/NaN/undefined/null/{};

下面的情況也是不可以的

var [a, [b]] = [1, 2];

它可以拆成var a = 1;和var [b] = 2;

第二個同樣不能解構賦值所以會報錯

默認賦值

可以使用下面這種語法實現默認的賦值

var [foo = 1] = [];
console.log(foo); //1

隻有當右側的值嚴格等於undefined才會使用默認賦值

var [foo = 1] = [null];
console.log(foo); //null

由於 null !== undefined
所以這裡foo被賦予null

惰性賦值

惰性賦值說的是默認賦值的機制, 隻有在需要使用默認值的時候 才會去求值

function foo(){
    alert(' ');
    return 123;
}
var [a = foo()] = [1]; //不彈窗
console.log(a); //1
var [a = foo()] = []; //彈窗
console.log(a); //123

解構順序

解構賦值首先會看右邊有沒有與之對應的值
沒有的話從左向右解析

var [a = 1, b = a] = [];
console.log(a, b); //1 1

這段代碼就相當於

var a = 1;
var b = a;

var [a = b, b = 1] = [];
console.log(a, b); //undefined 1

註意

如果這裡var 換成let就不一樣瞭

let [a = b, b = 1] = [];
console.log(a, b); //報錯

這段代碼可以看成

let a = b;
let b = 1;

由於let聲明沒有變量提升

所以此時b還未聲明就會報錯


可以看看這道題

var [x1 = 1, y1 = x1] = [];
var [x2 = 1, y2 = x2] = [2];
var [x3 = 1, y3 = x3] = [1,2];             
var [x4 = y4, y4 = 1] = [];   
console.log(x1,y1);//1 1
console.log(x2,y2);//2 2
console.log(x3,y3);//1 2
console.log(x4,y4);//undefined 1

同理如果上面的第四行的var換成let會報錯

對象解構

上面我們通過數組的形式瞭解瞭解構賦值

其實解構賦值不僅僅可以用數組

對象也可以

它們類似的地方就不再贅述瞭

基本用法

對象的解構賦值是按照屬性名(鍵)決定的

如果沒有找到對應的屬性,那就賦予undefined

var {foo, bar, foobar} = {
    foo: 1,
    bar: 2
}
console.log(foo, bar, foobar);//1 2 undefined

對於已經聲明過的變量要註意

var a;
{a} = {a: 1}; //錯誤

瀏覽器會報錯

因為js引擎把它理解成瞭代碼塊

而內部的代碼它不認識

解決辦法就是加上括號

這樣瀏覽器就可以知道這是一個表達式

var a;
({a} = {a: 1});

但是如果我們想要聲明的變量與屬性名不同怎麼辦呢

我們可以使用另一種模式

var {foo: a, bar: b, foobar: c = 100} = {
    foo: 1,
    bar: 2
}
console.log(a, b, c);//1 2 100

這相當於聲明瞭a和b變量

同樣可以使用默認賦值

字符串解構賦值

var [a, b, c, d, e] = 'hello';
console.log(a, b, c, d, e); //h e l l o

字符串被轉化為基本包裝對象(類數組對象)

所以可以實現

var {length : len} = 'hello';
console.log(len); //5

同理這個類數組對象中有length屬性

基本值解構賦值

如果等號右邊是數字或者佈爾值

也同樣會轉化為包裝對象

let {toString: a} = 123;
let {toString: b} = true;
console.log( a === Number.prototype.toString); //true
console.log( b === Boolean.prototype.toString); //true

但註意null和undefined沒有封裝對象

下面的代碼會報錯

let {toString: x } = undefined; //錯誤
let {toString: y } = null; //錯誤

函數參數的結構賦值

function add([x, y]) {
    return x + y;
}
console.log(add([1, 2]));

函數參數表面上是一個數組

但在傳入參數時,數組參數就被結構成變量 x 和 y

相當於var [x, y] = [1, 2]


function foo({x = 0, y = 0} = {}){
    console.log([x, y]);
}
foo({x: 1,y: 2}); //[1, 2]
foo({x: 1}); //[1, 0]
foo({}); //[0, 0]
foo(); //[0, 0]
function bar({x, y} = {x: 0, y: 0}){
    console.log([x, y]);
}     
bar({x: 1,y: 2}); //[1, 2]
bar({x: 1}); //[1, undefined]
bar({}); //[undefined, undefined]
bar(); //[0, 0]

解構賦值的應用

除瞭交換變量以外

解構賦值還有很多用途

函數多值返回

function demo(){
    return [1, 2, 3];
}
var [a, b, c] = demo();

函數定義參數

function demo({a, b, c}){
    ...
}
demo({a: 1, b: 2, c: 3});

提取JSON數據

var jsonData= {
    id: 66,
    status: 'OK',
    data: [123, 456]
}
let {id, status, data:number} = jsonData;

發佈留言