公棕號【前端便利貼】記錄著一個程式媛的所見所得所想,分享日常技術筆記,內容覆蓋了閱讀、技術和個人思考~,關注公棕號更早獲取更多文章。
覺得有用的話,小手點點【推薦】再走吖~~
【系統學習ES6】
本專題旨在對ES6的常用技術點進行系統性梳理,幫助大家對其有更好的掌握,希望大家有所收穫。
ES6允許按照一定模式,從數組和對象中提取值,對變數進行賦值,這被稱為解構。解構是一種打破數據結構,將其拆分為更小部分的過程。
傳統寫法中,從數組或對象中提取特定數據賦值給變數,編寫了很多結構相同,變數不同的程式碼,例如:
let option = { name:'foo', type:'string' }; let name = option.name; let type = option.type;
以上程式碼的作用是,從option對象中提取name和type兩個屬性,賦值給變數name和type。此時只有兩個變數,想像一下,如果有更多變數,那就要依次追加多句賦值。如果其中包含嵌套結構,那就要深入讀取層級,才能找到目標變數。
也許是為了解決這種困擾,所以ES6為對象和數組添加了解構功能,在合適的場景下運用,大大減少程式碼量,提高工作效率。
解構成功的前提,是左右兩側類型一致,即:如果是對象解構,左側被賦值變數必須包裝在{ }內,同理,數組解構,左側必須是[ ]。
上文強調過:對象的解構,左側必須是{ }。只要左側的變數在右側對象中有,即使位置不同,也可被成功賦值,但如果變數在右側沒有與之對應的屬性,則會被賦值為undefined。
let option = { name:'foo', type:'string' }; let { name, type } = option; // let { type, name } = option; // 此句與上句效果相同 console.log(name); // 'foo' console.log(type); // 'string' let { age } = option; console.log(age); // undefined let { name } = option; console.log(name); // 'foo'
注意:對象解構前,必須提供初始值(即右側的對象)。如果右側沒有值,程式會拋異常。
let { name }; // Uncaught SyntaxError:
如果變數名與對象屬性名不一致,可以通過解構對變數賦值么?ES6的另一個拓展語法可以幫助我們。
let option = { name:'foo', type:'string' }; let { name: attrName, type: attrType} = option; console.log(attrName); // 'foo' console.log(attrType); // 'string'
這實際上說明,對象的解構賦值是下面形式的簡寫:
let { name: attrName, type: attrType} = { name:'foo', type:'string' };
也就是說,對象的解構賦值的內部機制,是先找到同名屬性,然後再賦給對應的變數。真正被賦值的是後者,而不是前者。
可以單層解構賦值,就支援嵌套賦值。前提是左右兩邊形式一致。
let option = { name: 'foo', type: 'string', start: { row: 1, col: 0 } }; let { start: { row } } = option; console.log(row); // 1
數組的解構與對象有一個重要的不同。對象的解構按屬性名決定的,左右兩側變數位置可以不一致,但變數必須與屬性同名,才能取到正確的值。
數組的元素是按順序排列的,變數的取值由它的位置決定。只要等號兩邊類型相同(都是數組格式),左側變數會按照位置關係,被賦予右側數組的同的值。在這個過程中,右側數組本身不會發生變化。
let [name, type] = ['foo','string']; console.log(name); // 'foo' console.log(type); // 'string'
let [a, [b, c] = [1, [2, 3]]; console.log(name); // 1 console.log(type); // 2 console.log(height); // 3
如果左右形式不一致,可能會直接報錯:
let [a] = 1; // Uncaught TypeError: 1 is not iterable
如果右側數組元素數量比左側變數多,可以解構成功。屬於不完全匹配。
let [a, b] = [1, 2, 3]; console.log(a); // 1 console.log(b); // 2
如果右側數組元素數量比左側變數少,這種情況屬於解構失敗,解構失敗的變數會被賦值為undefined。
let [a, b] = [1]; console.log(a); // 1 console.log(b); // undefined let [a, b, ...c] = [1]; console.log(a); // 1 console.log(b); // undefined console.log(b); // []
此時,b是undefined理解,那c為什麼是數組?這不是解構的鍋,相關知識點,後面會討論到。
不管是數組還是對象,解構賦值都允許指定默認值。只有當右側相應屬性或位置的值全等(===)undefined,默認值才會生效。
數組:
let [a = 1] = []; // a=1 let [a, b = 2] = [1]; // a=1, b=2 let [a, b = 2] = [1, undefined]; // a=1, b=2 let [a, b = 2] = [1, null]; // a=1, b=null let [a, b = 2] = [1, ""]; // a=1, b=""
對象:
let { name, type = 'string' } = { name: 'foo'}; // name:'foo' type:'string' let { name, type = 'string' } = { name: 'foo', type: undefined}; // name:'foo' type:'string' let { name, type = 'string' } = { name: 'foo', type: null}; // name:'foo' type:'null' let { name, type = 'string' } = { name: 'foo', type: ''}; // name:'foo' type:''
(1)如果要將一個已經聲明的變數用於解構賦值,要注意一下寫法。
let name = 'bar'; { name } = { name: 'foo' }; console.log(name); // SyntaxError: syntax error
上面程式碼會報錯,因為 JavaScript 引擎會將{name}理解成一個程式碼塊,從而發生語法錯誤。只有不將大括弧寫在行首,才能解決這個問題。於是圓括弧來了。數組同理。
let name = 'bar'; ({ name } = { name: 'foo' }); console.log(name); // 'foo'
字元串也可以解構,這是因為,此時字元串被轉換成了一個類似數組的對象。
const [a,b,c,d,e]="lemoncool"; console.log(a); // l console.log(b); // e console.log(c); // m console.log(d); // 0 console.log(e); // n .....
討論完對象和數組的解構,其實可以基於二者來創造更複雜的表達式解構。比如json中,數組和對象混雜,此時想解析到某個資訊。是否可以實現呢?答案是肯定的,前提是格式要對應正確,篇幅有限,此處不再舉例。
解構,除了基礎的變數賦值外,用途還有很多。
1、交換變數的值
let x = 1; let y = 2; [x, y] = [y, x];
上面程式碼交換變數x和y的值,這樣的寫法不僅簡潔,而且易讀,語義非常清晰。
2、返回多個值
函數只能返回一個值,如果要返回多個值,只能將它們放在數組或對象里返回。有了解構賦值,取出這些值就非常方便。
function example() { return [1, 2, 3]; } let [a, b, c] = example();
3.引入腳手架中的指定方法
腳手架不想整體引入,可以指定引入某些方法。
import { cloneDeep, random } from 'lodash';
到此,變數解構的使用方法及注意事項已梳理完畢。
下一節我們會一起討論【拓展運算符和res運算符】,感謝大家支援,希望大家在每一節中都有所得。
公棕號【前端便利貼】記錄著一個程式媛的所見所得所想,分享日常技術筆記,內容覆蓋了閱讀、技術和個人思考~,關注公棕號更早獲取更多文章。
覺得有用的話,小手點點【推薦】再走吖~~