ES6中的解構(gòu)賦值
1、數(shù)組的解構(gòu)賦值
1.1、基本用法
按照“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應(yīng)的值。
let [a, b, c] = [1, 2, 3]; //a為1,b為2,c為3 let [foo, [[bar], baz]] = [1, [[2], 3]]; //foo: 1 bar: 2 baz: 3 let [ , , third] = ["foo", "bar", "baz"]; //third: "baz" let [x, , y] = [1, 2, 3]; //x: 1 y: 3 let [head, ...tail] = [1, 2, 3, 4]; //head: 1 tail: [2, 3, 4] let [x, y, ...z] = ['a']; //x: "a" y: undefined z: []
如果左邊的值匹配不上,就會被賦值為undefined。
1.2、指定默認(rèn)值
解構(gòu)賦值允許指定默認(rèn)值。ES6 內(nèi)部使用嚴(yán)格相等運(yùn)算符(===),判斷等號右邊該位置是否有值。所以,等號右邊該值嚴(yán)格等于undefined(空也等于undefined),左邊的默認(rèn)值才會生效。
let [foo = true] = []; //foo: true let [x, y = 'b'] = ['a']; // x='a', y='b' let [x, y = 'b'] = ['a', undefined]; // x='a', y='b' let [x = 1] = [undefined]; //x:1 let [x = 1] = [null]; //x:null
1.3、報錯情況(等號右邊不是數(shù)組、默認(rèn)值引用未定義變量)
如果等號的右邊不是數(shù)組(或者嚴(yán)格地說如果不是可遍歷的結(jié)構(gòu)),那么將會報錯。
// 報錯 let [foo] = 1; let [foo] = false; let [foo] = NaN; let [foo] = undefined; let [foo] = null; let [foo] = {};
默認(rèn)值可以引用其他的變量,但該變量必須已經(jīng)聲明過,否則將會報錯。
let [x = 1, y = x] = []; // x=1; y=1 let [x = 1, y = x] = [2]; // x=2; y=2 let [x = 1, y = x] = [1, 2]; // x=1; y=2 let [x = y, y = 1] = []; // ReferenceError: y is not defined 此時在x用y做默認(rèn)值時,y還沒有聲明。
2、對象的解構(gòu)賦值
2.1、基本用法
對象的解構(gòu)與數(shù)組不太一樣,數(shù)組的元素是按次序排列的,變量的取值由位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。
let { foo, bar } = { foo: 'aaa', bar: 'bbb' }; //foo:"aaa" bar:"bbb"
let { bar, foo } = { foo: 'aaa', bar: 'bbb' }; //foo:"aaa" bar:"bbb" 次序不影響賦值,變量名才影響
let { baz } = { foo: 'aaa', bar: 'bbb' }; //baz:undefined 變量名匹配不上將會賦值為undefined
如果變量名與屬性名不一致,可以寫成這樣:
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; //baz:"aaa"
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj; //f: 'hello' l: 'world'
對象的解構(gòu)賦值的內(nèi)部機(jī)制,是先找到等號左邊的同名屬性,然后再賦給左邊對應(yīng)的變量。真正被賦值的是左邊同名屬性后面的變量,而不是那個同名屬性。
2.2、默認(rèn)值
對象的解構(gòu)也可以指定默認(rèn)值。
var {x = 3} = {}; //x: 3 var {x, y = 5} = {x: 1}; //x: 1 y: 5 var {x: y = 3} = {}; //y: 3 var {x: y = 3} = {x: 5}; //y: 5 var { message: msg = 'Something went wrong' } = {}; //msg: "Something went wrong"
默認(rèn)值生效的條件是,等號右邊對象的屬性值嚴(yán)格等于undefined。
var {x = 3} = {x: undefined}; //x: 3 var {x = 3} = {x: null}; //x: null
2.3、報錯情況(給已經(jīng)定義好的變量賦值可能會報錯)
給已經(jīng)定義好的變量進(jìn)行解構(gòu)賦值有可能會報錯:
let a, b; {a, b} = {a: 123, b: 456}; // 報錯顯示:Uncaught SyntaxError: Unexpected token =
上面的代碼將會報錯,因為 JS 引擎遇到 {} 會當(dāng)成一個代碼塊,語法規(guī)定,代碼塊語句不允許出現(xiàn)在賦值語句左側(cè)。
所以解構(gòu)賦值時' { '符號不能出現(xiàn)在一行的最前面。在添加小括號后可以將塊語句轉(zhuǎn)化為一個表達(dá)式,從而實(shí)現(xiàn)整個解構(gòu)賦值過程。
let a, b; ({a, b} = {a: 123, b: 456}); console.log(a, b) // 123 456
2.4、解構(gòu)賦值淺拷貝問題
解構(gòu)賦值的拷貝是淺拷貝,如果一個鍵的值是復(fù)合類型的值(數(shù)組、對象、函數(shù))、那么解構(gòu)賦值拷貝的是這個值的引用,而不是這個值的副本。
let obj = { a: { b: 1 }, c: 100 };
let { ...x } = obj; //obj中 a 的值是對象,所以解構(gòu)賦值時拷貝的是 a 的引用,而 c 的值是簡單類型,所以obj.c改變不影響x
obj.a.b = 2; obj.c = 200;
console.log(x.a.b,c) // 2 100
3、函數(shù)參數(shù)的解構(gòu)賦值
3.1、基本用法
function add([x, y]){ return x + y; } add([1, 2]); // 3
3.2、默認(rèn)值
(1)普通參數(shù)默認(rèn)值:
function show(age, name='www', c=false) { console.log(age, name, c); } show(); //undefined "www" false show(12); //12 "www" false show(12, 'aaa'); //12 "aaa" false show(12, 'aaa', true); //12 "aaa" true
(2)當(dāng)函數(shù)的參數(shù)是一個對象時,默認(rèn)值的寫法:
function move({x = 0, y = 0} = {}) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, 0] move({}); // [0, 0] move(); // [0, 0]
上面代碼中,{x=0, y=0} 意思是x,y的默認(rèn)值分別是0,后面的={}意思是如果函數(shù)沒有傳參時參數(shù)默認(rèn)是{},而且由于前面給x,y默認(rèn)值了,所以總的來說,參數(shù)的默認(rèn)值是{x=0, y=0}。
如果沒有寫后面的={},直接 move() 這樣調(diào)用將會報錯,但其他形式的調(diào)用不會有問題。實(shí)際上后面的 ={} 才表示默認(rèn)值。
注意,下面的寫法會得到不一樣的結(jié)果。
function move({x, y} = { x: 0, y: 0 }) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, undefined] move({}); // [undefined, undefined] move(); // [0, 0]
上面的寫法表示的是函數(shù)的參數(shù)默認(rèn)是{x:0, y:0},但如果有參數(shù)的話即使參數(shù)只傳x的值,此時默認(rèn)值便不起作用。

浙公網(wǎng)安備 33010602011771號