【系統學習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運算符】,感謝大家支援,希望大家在每一節中都有所得。
公棕号【前端便利貼】記錄着一個程式媛的所見所得所想,分享日常技術筆記,内容覆寫了閱讀、技術和個人思考~,關注公棕号更早擷取更多文章。
覺得有用的話,小手點點【推薦】再走吖~~
作者:Lemoncool
出處:https://www.cnblogs.com/lemoncool/
更多:沒有辦法維護原創版權,歡迎關注我的公粽号:前端便利貼,文章更早、更全,免費擷取完整代碼
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連結,否則保留追究法律責任的權利.