您好,登錄后才能下訂單哦!
小編給大家分享一下JS ES新特性之變量的解耦賦值怎么用,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
ECMAScript 2015中允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為 解耦賦值 。
在ECMAScript 2015之前中為變量賦值的方式如下所示:
let a = 1; let b = 2; let c = 3;
在ECMAScript 2015允許寫成下面這樣。
let [a, b, c] = [1, 2, 3];
ECMAScript 2015
的解耦賦值本質上屬于模式匹配。賦值運算符兩邊的模式相同,左邊的變量會被賦予對應位置的值。
如果解耦賦值失敗的話,變量的值等于 undefined。示例代碼如下所示:
// 如果數組的某個索引值的位置的變量,在 = 運算符的右邊沒有數組中沒有對應的索引值與之對應,則解耦賦值失敗,其值為 undefined let [v] = [] let [a, b] = [1] console.log(v, a, b); // undefined 1, undefined
如果想解決解耦賦值失敗的問題,需要將其賦值運算符的左右兩邊的數量保持一致。
所謂的不完全解耦賦值就是指賦值運算符的右邊數組中的數量要大于左邊數組中的數量,導致右邊數組中的有些變量失效,但是這這種情況下解耦賦值還是會成功的。
示例代碼如下所示:
// 賦值運算符左邊變量的數量小于右邊值的數量 let [a, b, c] = [1, 2, 3, 4] // 依然會解耦賦值成功 console.log(a, b, c); // 1 2 3
解耦賦值允許指定默認值的。示例代碼如下所示:
/* * 解耦賦值中允許指定默認值 * 語法結構如下 * let [var1 = value1, var2 = value2 ,...] = [val1, val2,...] var1,var2 表示變量名 value1,value2 表示默認值 val1,val2, 表示指定的值 */ let [a = 1, b = 2] = [100] console.log(a, b); // 100 2
在使用默認值的時候值得注意的一點就是,ECMAScript6
內部會使用全等于 === 運算符來判斷指定位置的值是否全等于undefined
。只有當 全等于undefined時,其默認值才會生效。
測試代碼如下所示:
let [a = 1, b = 2] = [100, undefined] console.log(a, b); // 100 2
當我們使用null值時,雖然null
也表示為空,但是null !== undefined
。所以我們的默認值并不會生效,
測試代碼如下:
let [a = 1, b = 2] = [100, null] console.log(a, b); // 100 null
由于JavaScript
是一個弱類型的語言,所以賦值號右邊是什么類型都是允許的,那就會出現以下幾種特殊情況:
情況一:運算符右邊是一個函數,示例代碼如下
// 1. 運算符右邊是一個函數 let [a, b] = [1, function () { return 10; }] console.log(b()); // 10
情況二:運算符右邊是一個對象,示例代碼如下
// 2. 運算符右邊是一個對象 let [a, b] = [1, { name: '狐妖小紅娘' }] console.log(b); // { name: '狐妖小紅娘' }
情況三:運算符右邊函數數組,示例代碼如下
// 3. 運算符右邊是含有數組 let [a, b] = [1, [2, 3]] console.log(b); // [ 2, 3 ]
情況四:運算符左右兩邊都含有數組,示例代碼如下所示
// 4. 運算符左右兩邊都含有數組,示例代碼如下所示 let [a, [b, c]] = [1, [2, 3]] console.log(b); // 2
對象的解耦賦值是通過變量名稱實現與對象的屬性名稱一一對應實現的。示例代碼如下所示:
/* * 對象的解耦賦值 - 從對象中提取值,為變量賦值 ! 變量名稱必須與對象的屬性名稱一一對應,否則就會導致失敗。 */ let { x, y } = { x: 10, y: 20 } console.log(x, y); //10 20
值得注意的是賦值運算符兩邊的格式需要保持一致。
由于 JavaScript
是一個弱類型的語言,所以賦值號右邊是什么類型都是允許的,那就會出現以下幾種特殊情況:
情況一:運算符右邊是一個函數,示例代碼如下
// 1. 運算符右邊是一個函數 let { a, b } = { a: 1, b: function () { return 10; } } console.log(b());// 10
情況二:運算符右邊是一個對象,示例代碼如下
// 2. 運算符右邊是一個對象 let {a, b} = { a: 1, b: { name: 'ywanzhou' } } console.log(b); // { name: 'ywanzhou' }
情況三:運算符右邊函數數組,示例代碼如下
// 3. 運算符右邊是含有數組 let {a, b} = { a: 1, b: [1, 2] } console.log(b); //[ 1, 2 ]
情況四:運算符左右兩邊都含有對象,示例代碼如下所示
// 4. 運算符左右兩邊都含有對象 let { m: { name, age }, n } = { m: { name: 'test', age: 20 }, n: 20 } console.log(name, age); // test 20
如果解耦賦值失敗的話,變量的值等于undefined。示例代碼如下所示:
// 解耦賦值失敗 let { a, b } = { a: 10 } console.log(b);
所謂的不完全解耦賦值就是指賦值運算符的右邊對象中屬性的數量要大于左邊對象中屬性的數量,導致右邊對象中屬性的有些變量失效,但是這這種情況下解耦賦值還是會成功的。
// 不完全解耦賦值 let { a } = { a: 10, b: 20 } console.log(a);
解耦賦值允許指定默認值的。示例代碼如下所示:
// 默認值 let { a, b = 100 } = { a: 10, b: 20 } console.log(b);
字符串也可以解構賦值。這是因為此時,字符串被轉換成了一個類似數組的對象。
let [h2, y, x] = "一碗周" console.log(h2, y, x, h3); // 一 碗 周
如果直接對數字值/布爾值進行解耦賦值會拋出異常,在對數字值和布爾值進行操作時,其賦值運算符的右邊是數值和布爾值,則會先轉為對象。
// let [a] = 100; // 拋出異常 描述信息為 TypeError: 100 is not iterable // console.log(a); // 對布爾或者數值進行解耦賦值的話, 需要現將其改變成為對象類型。 let { toString: b } = 1; console.log(b === Number.prototype.toString); // true let { toString: c } = true; console.log(c === Boolean.prototype.toString); // true
解構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉為對象。由于undefined
和null
無法轉為對象,所以對它們進行解構賦值,都會報錯。
函數的參數也可以使用解構賦值。示例代碼如下所示:
// 使用數組 function f([a, b]) { console.log(a, b); } f([10, 20]) // 10 20 // 使用對象 function fn({ a, b }) { console.log(a, b); } fn({ a: 10, b: 20 }) // 10 20
解耦賦值雖然很方便,但是解析起來并不容易。對于編譯器來說,一個式子到底是模式,還是表達式,沒有辦法從一開始就知道,必須解析到(或解析不到)等號才能知道。
由此帶來的問題是,如果模式中出現小括號怎么處理。ECMAScript 2015
的規則是,只要有可能導致解構的歧義,就不得使用小括號。
但是,這條規則實際上不那么容易辨別,處理起來相當麻煩。因此,建議只要有可能,就不要在模式中放置小括號。
如下三種情況不能使用小括號
情況一:變量聲明語句,示例代碼如下所示
// 如下情況全部會報錯 let [(a)] = [1]; let {x: (c)} = {}; let ({x: c}) = {}; let {(x: c)} = {}; let {(x): c} = {}; let { o: ({ p: p }) } = { o: { p: 2 } };
上面6個語句都會報錯,因為它們都是變量聲明語句,模式不能使用小括號。
情況二:作為函數參數
函數參數也屬于變量聲明,因此不能帶有小括號。
// 報錯 function f([(z)]) { return z; } // 報錯 function f([z,(x)]) { return x; }
情況三:賦值語句的模式
// 全部報錯 ({ p: a }) = { p: 42 }; ([a]) = [5];
上面代碼將整個模式放在小括號之中,導致報錯。
// 報錯 [({ p: a }), { x: c }] = [{}, {}];
上面代碼將一部分模式放在小括號之中,導致報錯。
可以使用小括號的情況只有一種:賦值語句的非模式部分,可以使用小括號。
[(b)] = [3]; // 正確 ({ p: (d) } = {}); // 正確 [(parseInt.prop)] = [3]; // 正確
上面三行語句都可以正確執行,因為首先它們都是賦值語句,而不是聲明語句;其次它們的小括號都不屬于模式的一部分。第一行語句中,模式是取數組的第一個成員,跟小括號無關;第二行語句中,模式是p,而不是d;第三行語句與第一行語句的性質一致。
變量解耦賦值的用處有很多,下面舉幾個比較常見的例子。
如果沒有解耦賦值交換變量需要借助第三個變量才能完成,示例代碼如下所示:
var a = 10, b = 20; var c = a; a = b b = c c = null /// 釋放變量 console.log(a, b); // 20 10
借助變量解耦賦值完成 ,示例代碼如下所示:
let a = 10, b = 20; [a, b] = [b, a] console.log(a, b); // 20 10
使用這種方式不僅簡潔,而且易讀,語義清晰。
函數只能返回一個值,如果要返回多個值,只能將它們放在數組或對象里返回。有了解構賦值,取出這些值就非常方便。
示例代碼如下所示:
// 返回一個數組 function example() { return [1, 2, 3]; } let [a, b, c] = example(); // 返回一個對象 function example() { return { foo: 1, bar: 2 }; } let { foo, bar } = example();
解構賦值可以方便地將一組參數與變量名對應起來。
// 參數是一組有次序的值 function f([x, y, z]) { console.log(x, y, z); } f([1, 2, 3]); // 1 2 3 // 參數是一組無次序的值 function fn({x, y, z}) { console.log(x, y, z); } fn({ z: 3, y: 2, x: 1 }); // 1 2 3
解構賦值對提取 JSON 對象中的數據,尤其有用。
// 提取json數據 let jsonData = { id: 42, status: "OK", data: [867, 5309] }; let { id, status, data: number } = jsonData; console.log(id, status, number); // 42, "OK", [867, 5309]
看完了這篇文章,相信你對“JS ES新特性之變量的解耦賦值怎么用”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。