JS?ES新特性之變量的解耦賦值
1.數(shù)組的解耦賦值
1.1數(shù)組解耦賦值是什么
ECMAScript 2015中允許按照一定模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,這被稱(chēng)為 解耦賦值 。
在ECMAScript 2015之前中為變量賦值的方式如下所示:
let a = 1; let b = 2; let c = 3;
在ECMAScript 2015允許寫(xiě)成下面這樣。
let [a, b, c] = [1, 2, 3];
ECMAScript 2015
的解耦賦值本質(zhì)上屬于模式匹配。賦值運(yùn)算符兩邊的模式相同,左邊的變量會(huì)被賦予對(duì)應(yīng)位置的值。
1.2數(shù)組解耦賦值失敗
如果解耦賦值失敗的話(huà),變量的值等于 undefined。示例代碼如下所示:
// 如果數(shù)組的某個(gè)索引值的位置的變量,在 = 運(yùn)算符的右邊沒(méi)有數(shù)組中沒(méi)有對(duì)應(yīng)的索引值與之對(duì)應(yīng),則解耦賦值失敗,其值為 undefined let [v] = [] let [a, b] = [1] console.log(v, a, b); // undefined 1, undefined
如果想解決解耦賦值失敗的問(wèn)題,需要將其賦值運(yùn)算符的左右兩邊的數(shù)量保持一致。
1.3不完全解耦賦值
所謂的不完全解耦賦值就是指賦值運(yùn)算符的右邊數(shù)組中的數(shù)量要大于左邊數(shù)組中的數(shù)量,導(dǎo)致右邊數(shù)組中的有些變量失效,但是這這種情況下解耦賦值還是會(huì)成功的。
示例代碼如下所示:
// 賦值運(yùn)算符左邊變量的數(shù)量小于右邊值的數(shù)量 let [a, b, c] = [1, 2, 3, 4] // 依然會(huì)解耦賦值成功 console.log(a, b, c); // 1 2 3
1.4默認(rèn)值
解耦賦值允許指定默認(rèn)值的。示例代碼如下所示:
/* * 解耦賦值中允許指定默認(rèn)值 * 語(yǔ)法結(jié)構(gòu)如下 * let [var1 = value1, var2 = value2 ,...] = [val1, val2,...] var1,var2 表示變量名 value1,value2 表示默認(rèn)值 val1,val2, 表示指定的值 */ let [a = 1, b = 2] = [100] console.log(a, b); // 100 2
在使用默認(rèn)值的時(shí)候值得注意的一點(diǎn)就是,ECMAScript6
內(nèi)部會(huì)使用全等于 === 運(yùn)算符來(lái)判斷指定位置的值是否全等于undefined
。只有當(dāng) 全等于undefined時(shí),其默認(rèn)值才會(huì)生效。
測(cè)試代碼如下所示:
let [a = 1, b = 2] = [100, undefined] console.log(a, b); // 100 2
當(dāng)我們使用null值時(shí),雖然null
也表示為空,但是null !== undefined
。所以我們的默認(rèn)值并不會(huì)生效,
測(cè)試代碼如下:
let [a = 1, b = 2] = [100, null] console.log(a, b); // 100 null
1.5數(shù)組解耦賦值的復(fù)雜情況
由于JavaScript
是一個(gè)弱類(lèi)型的語(yǔ)言,所以賦值號(hào)右邊是什么類(lèi)型都是允許的,那就會(huì)出現(xiàn)以下幾種特殊情況:
情況一:運(yùn)算符右邊是一個(gè)函數(shù),示例代碼如下
// 1. 運(yùn)算符右邊是一個(gè)函數(shù) let [a, b] = [1, function () { return 10; }] console.log(b()); // 10
情況二:運(yùn)算符右邊是一個(gè)對(duì)象,示例代碼如下
// 2. 運(yùn)算符右邊是一個(gè)對(duì)象 let [a, b] = [1, { name: '狐妖小紅娘' }] console.log(b); // { name: '狐妖小紅娘' }
情況三:運(yùn)算符右邊函數(shù)數(shù)組,示例代碼如下
// 3. 運(yùn)算符右邊是含有數(shù)組 let [a, b] = [1, [2, 3]] console.log(b); // [ 2, 3 ]
情況四:運(yùn)算符左右兩邊都含有數(shù)組,示例代碼如下所示
// 4. 運(yùn)算符左右兩邊都含有數(shù)組,示例代碼如下所示 let [a, [b, c]] = [1, [2, 3]] console.log(b); // 2
2.對(duì)象的解耦賦值
對(duì)象的解耦賦值是通過(guò)變量名稱(chēng)實(shí)現(xiàn)與對(duì)象的屬性名稱(chēng)一一對(duì)應(yīng)實(shí)現(xiàn)的。示例代碼如下所示:
/* * 對(duì)象的解耦賦值 - 從對(duì)象中提取值,為變量賦值 ! 變量名稱(chēng)必須與對(duì)象的屬性名稱(chēng)一一對(duì)應(yīng),否則就會(huì)導(dǎo)致失敗。 */ let { x, y } = { x: 10, y: 20 } console.log(x, y); //10 20
值得注意的是賦值運(yùn)算符兩邊的格式需要保持一致。
2.1對(duì)象解耦賦值的特殊情況
由于 JavaScript
是一個(gè)弱類(lèi)型的語(yǔ)言,所以賦值號(hào)右邊是什么類(lèi)型都是允許的,那就會(huì)出現(xiàn)以下幾種特殊情況:
情況一:運(yùn)算符右邊是一個(gè)函數(shù),示例代碼如下
// 1. 運(yùn)算符右邊是一個(gè)函數(shù) let { a, b } = { a: 1, b: function () { return 10; } } console.log(b());// 10
情況二:運(yùn)算符右邊是一個(gè)對(duì)象,示例代碼如下
// 2. 運(yùn)算符右邊是一個(gè)對(duì)象 let {a, b} = { a: 1, b: { name: 'ywanzhou' } } console.log(b); // { name: 'ywanzhou' }
情況三:運(yùn)算符右邊函數(shù)數(shù)組,示例代碼如下
// 3. 運(yùn)算符右邊是含有數(shù)組 let {a, b} = { a: 1, b: [1, 2] } console.log(b); //[ 1, 2 ]
情況四:運(yùn)算符左右兩邊都含有對(duì)象,示例代碼如下所示
// 4. 運(yùn)算符左右兩邊都含有對(duì)象 let { m: { name, age }, n } = { m: { name: 'test', age: 20 }, n: 20 } console.log(name, age); // test 20
2.2解耦賦值失敗
如果解耦賦值失敗的話(huà),變量的值等于undefined。示例代碼如下所示:
// 解耦賦值失敗 let { a, b } = { a: 10 } console.log(b);
2.3不完全解耦賦值
所謂的不完全解耦賦值就是指賦值運(yùn)算符的右邊對(duì)象中屬性的數(shù)量要大于左邊對(duì)象中屬性的數(shù)量,導(dǎo)致右邊對(duì)象中屬性的有些變量失效,但是這這種情況下解耦賦值還是會(huì)成功的。
// 不完全解耦賦值 let { a } = { a: 10, b: 20 } console.log(a);
2.4默認(rèn)值
解耦賦值允許指定默認(rèn)值的。示例代碼如下所示:
// 默認(rèn)值 let { a, b = 100 } = { a: 10, b: 20 } console.log(b);
3.字符串、數(shù)值、和布爾值的解耦賦值
3.1字符串解耦賦值
字符串也可以解構(gòu)賦值。這是因?yàn)榇藭r(shí),字符串被轉(zhuǎn)換成了一個(gè)類(lèi)似數(shù)組的對(duì)象。
let [h1, y, x] = "一碗周" console.log(h1, y, x, h2); // 一 碗 周
3.2數(shù)值和布爾值的解耦賦值
如果直接對(duì)數(shù)字值/布爾值進(jìn)行解耦賦值會(huì)拋出異常,在對(duì)數(shù)字值和布爾值進(jìn)行操作時(shí),其賦值運(yùn)算符的右邊是數(shù)值和布爾值,則會(huì)先轉(zhuǎn)為對(duì)象。
// let [a] = 100; // 拋出異常 描述信息為 TypeError: 100 is not iterable // console.log(a); // 對(duì)布爾或者數(shù)值進(jìn)行解耦賦值的話(huà), 需要現(xiàn)將其改變成為對(duì)象類(lèi)型。 let { toString: b } = 1; console.log(b === Number.prototype.toString); // true let { toString: c } = true; console.log(c === Boolean.prototype.toString); // true
解構(gòu)賦值的規(guī)則是,只要等號(hào)右邊的值不是對(duì)象或數(shù)組,就先將其轉(zhuǎn)為對(duì)象。由于undefined
和null
無(wú)法轉(zhuǎn)為對(duì)象,所以對(duì)它們進(jìn)行解構(gòu)賦值,都會(huì)報(bào)錯(cuò)。
4.函數(shù)的解耦賦值
函數(shù)的參數(shù)也可以使用解構(gòu)賦值。示例代碼如下所示:
// 使用數(shù)組 function f([a, b]) { console.log(a, b); } f([10, 20]) // 10 20 // 使用對(duì)象 function fn({ a, b }) { console.log(a, b); } fn({ a: 10, b: 20 }) // 10 20
5.小括號(hào)的問(wèn)題
解耦賦值雖然很方便,但是解析起來(lái)并不容易。對(duì)于編譯器來(lái)說(shuō),一個(gè)式子到底是模式,還是表達(dá)式,沒(méi)有辦法從一開(kāi)始就知道,必須解析到(或解析不到)等號(hào)才能知道。
由此帶來(lái)的問(wèn)題是,如果模式中出現(xiàn)小括號(hào)怎么處理。ECMAScript 2015
的規(guī)則是,只要有可能導(dǎo)致解構(gòu)的歧義,就不得使用小括號(hào)。
但是,這條規(guī)則實(shí)際上不那么容易辨別,處理起來(lái)相當(dāng)麻煩。因此,建議只要有可能,就不要在模式中放置小括號(hào)。
5.1不能使用小括號(hào)的情況
如下三種情況不能使用小括號(hào)
情況一:變量聲明語(yǔ)句,示例代碼如下所示
// 如下情況全部會(huì)報(bào)錯(cuò) let [(a)] = [1]; let {x: (c)} = {}; let ({x: c}) = {}; let {(x: c)} = {}; let {(x): c} = {}; let { o: ({ p: p }) } = { o: { p: 2 } };
上面6個(gè)語(yǔ)句都會(huì)報(bào)錯(cuò),因?yàn)樗鼈兌际亲兞柯暶髡Z(yǔ)句,模式不能使用小括號(hào)。
情況二:作為函數(shù)參數(shù)
函數(shù)參數(shù)也屬于變量聲明,因此不能帶有小括號(hào)。
// 報(bào)錯(cuò) function f([(z)]) { return z; } // 報(bào)錯(cuò) function f([z,(x)]) { return x; }
情況三:賦值語(yǔ)句的模式
// 全部報(bào)錯(cuò) ({ p: a }) = { p: 42 }; ([a]) = [5];
上面代碼將整個(gè)模式放在小括號(hào)之中,導(dǎo)致報(bào)錯(cuò)。
// 報(bào)錯(cuò) [({ p: a }), { x: c }] = [{}, {}];
上面代碼將一部分模式放在小括號(hào)之中,導(dǎo)致報(bào)錯(cuò)。
5.2可以使用小括號(hào)的情況
可以使用小括號(hào)的情況只有一種:賦值語(yǔ)句的非模式部分,可以使用小括號(hào)。
[(b)] = [3]; // 正確 ({ p: (d) } = {}); // 正確 [(parseInt.prop)] = [3]; // 正確
上面三行語(yǔ)句都可以正確執(zhí)行,因?yàn)槭紫人鼈兌际琴x值語(yǔ)句,而不是聲明語(yǔ)句;其次它們的小括號(hào)都不屬于模式的一部分。第一行語(yǔ)句中,模式是取數(shù)組的第一個(gè)成員,跟小括號(hào)無(wú)關(guān);第二行語(yǔ)句中,模式是p,而不是d;第三行語(yǔ)句與第一行語(yǔ)句的性質(zhì)一致。
6.變量解耦賦值的用處
變量解耦賦值的用處有很多,下面舉幾個(gè)比較常見(jiàn)的例子。
6.1交換變量的值
如果沒(méi)有解耦賦值交換變量需要借助第三個(gè)變量才能完成,示例代碼如下所示:
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
使用這種方式不僅簡(jiǎn)潔,而且易讀,語(yǔ)義清晰。
6.2從函數(shù)返回多個(gè)值
函數(shù)只能返回一個(gè)值,如果要返回多個(gè)值,只能將它們放在數(shù)組或?qū)ο罄锓祷亍S辛私鈽?gòu)賦值,取出這些值就非常方便。
示例代碼如下所示:
// 返回一個(gè)數(shù)組 function example() { return [1, 2, 3]; } let [a, b, c] = example(); // 返回一個(gè)對(duì)象 function example() { return { foo: 1, bar: 2 }; } let { foo, bar } = example();
6.3函數(shù)參數(shù)的定義
解構(gòu)賦值可以方便地將一組參數(shù)與變量名對(duì)應(yīng)起來(lái)。
// 參數(shù)是一組有次序的值 function f([x, y, z]) { console.log(x, y, z); } f([1, 2, 3]); // 1 2 3 // 參數(shù)是一組無(wú)次序的值 function fn({x, y, z}) { console.log(x, y, z); } fn({ z: 3, y: 2, x: 1 }); // 1 2 3
6.4提取 JSON 數(shù)據(jù)
解構(gòu)賦值對(duì)提取 JSON 對(duì)象中的數(shù)據(jù),尤其有用。
// 提取json數(shù)據(jù) let jsonData = { id: 42, status: "OK", data: [867, 5309] }; let { id, status, data: number } = jsonData; console.log(id, status, number); // 42, "OK", [867, 5309]
到此這篇關(guān)于JS ES新特性之變量的解耦賦值的文章就介紹到這了,更多相關(guān)ES變量的解耦賦值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在微信小程序中渲染HTML內(nèi)容3種解決方案及分析與問(wèn)題解決
在開(kāi)發(fā)微信小程序時(shí)我們會(huì)在小程序內(nèi)加入純HTML代碼,且HTML中包括圖片,視頻,甚至是事件,微信小程序?yàn)槲覀兲峁┝?種解決方法,但它們的功能與實(shí)現(xiàn)方式與最終效果并不理想2020-01-01微信小程序中頁(yè)面FOR循環(huán)和嵌套循環(huán)
這篇文章主要介紹了微信小程序中頁(yè)面FOR循環(huán)和嵌套循環(huán)的相關(guān)資料,需要的朋友可以參考下2017-06-06詳解如何使用mock.js實(shí)現(xiàn)接口測(cè)試的自動(dòng)化
這篇文章主要為大家介紹了如何使用mock.js實(shí)現(xiàn)接口測(cè)試的自動(dòng)化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06微信小程序之頁(yè)面跳轉(zhuǎn)和參數(shù)傳遞的實(shí)現(xiàn)
這篇文章主要介紹了微信小程序之頁(yè)面跳轉(zhuǎn)和參數(shù)傳遞的實(shí)現(xiàn)的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09Promise靜態(tài)四兄弟實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了Promise靜態(tài)四兄弟實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07THREE.js添加多個(gè)castShadow光源報(bào)錯(cuò)解決及原因分析
這篇文章主要介紹了THREE.js添加多個(gè)castShadow的光源報(bào)錯(cuò)解決及原因分析2023-06-06Javascript繼承(上)——對(duì)象構(gòu)建介紹
Javascript中除了基本數(shù)據(jù)(Undefined、Null、Boolean、Number、String),其他都是對(duì)象(Object)2012-11-11