ECMAScript 2015 提供了很有創意的 Object Destructuring,原本需要好幾行才能完成的 Code,只需要一行就能解決。
Version
macOS Mojave 10.14.5
VS Code 1.36.1
Quokka 1.0.238
ECMAScript 2015
Basic Assignment
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let firstName = obj.firstName;
let lastName = obj.lastName;
console.log(firstName, lastName);
obj
有 firstName
與 lastName
兩個 property,想建立兩個變數也是 firstName
與 lastName
,ECMAScript 5 寫法必須要 2 行。
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let { firstName, lastName } = obj;
console.log(firstName, lastName);
ES6 將變數名稱直接寫在 object literal 內,object 會依照變數名稱去尋找 property 名稱,直接分解到變數,只需 1 行。
New Variable Name
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let givenName = obj.firstName;
let familyName = obj.lastName;
console.log(givenName, familyName);
若變數名稱與 key 不同,在 ES5 必須寫 2 行。
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let { firstName: givenName, lastName: familyName } = obj;
console.log(givenName, familyName);
在 ES6 的 object destructuring 分解變數時,預設變數名稱與 property 名稱相同,若要改變變數名稱,可加上 :
,並在 :
右側加上新的變數名稱。
Cloning Object
let obj1 = {
firstName: 'Sam',
lastName: 'Xiao'
};
let obj2 = obj1;
obj2; // ?
obj2 === obj1; // ?
若要複製 object,直覺會使用 =
,但這只是將 reference 加以複製,所以 obj1
與 obj2
指向同一個 object,而不是真的複製 object。
let obj1 = {
firstName: 'Sam',
lastName: 'Xiao',
};
let obj2 = Object.assign({}, obj1);
obj2; // ?
obj2 === obj1; // ?
ES5 可使用 Object.assign()
將 object 加以複製,assign()
是真的回傳一個新的 object,而非指向同一個 object。
let obj1 = {
firstName: 'Sam',
lastName: 'Xiao',
};
let { ...obj2 } = obj1;
obj2; // ?
obj2 === obj1; // ?
ES6 則有新的寫法,object destructuring 配合 ...
spread operator,其結果等同於 ES5 的 Object.assign()
。
Function Parameter
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let func = function(args) {
let firstName = args.firstName;
let lastName = args.lastName;
console.log(firstName, lastName);
};
func(obj);
若 parameter 為 object,ES5 會使用 .
的方式存取 property key,需要 2 行。
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let func = ({ firstName, lastName }) => console.log(firstName, lastName);
func(obj);
ES6 可在 parameter 使用 object destructuring,直接在 parameter list 分解成變數。
雖然只是一個 object,但若使用 arrow function 時,仍須加上 ()
將 object 刮起來。
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let func = ({ firstName, lastName, age = 20 }) => console.log(firstName, lastName, age);
func(obj);
若想提供 default value 也行,在 =
之後提供 default value 即可。
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let func = ({ firstName: givenName, lastName: familyName, age = 20 }) => console.log(givenName, familyName, age);
func(obj);
若想同時改變 parameter 名稱,並提供 default value,也可以同時寫在 parameter list。
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let func = ({ firstName = 'John', lastName = 'Doe', age = 20 } = {}) => console.log(firstName, lastName, age);
func();
若 object 是 optional parameter,可加上 =
,並在右側加上 {}
。
let obj = {
firstName: 'Sam',
lastName: 'Xiao',
};
let func = (args = {}) => {
let {
firstName = 'John',
lastName = 'Doe',
age = 20,
} = args;
console.log(firstName, lastName, age);
};
func();
若要分解的 parameter 太多,通通寫在 parameter list 導致可讀性不佳,其實可考慮在 parameter list 只寫 optional parameter,而 object destructuring 與 default value 寫在 function body。
let obj = {
id: 1,
name: 'Sam',
scores: {
math: 90,
english: 80,
},
};
let func = function(args) {
let id = args.id;
let name = args.name;
let math = args.scores.math;
let english = args.scores.english;
console.log(id, name, math, english);
};
func(obj);
若 parameter 為 nested object,ES5 必須一一分解變數,需要 4 行。
let obj = {
id: 1,
name: 'Sam',
scores: {
math: 90,
english: 80,
},
};
let func = ({ id, name, scores: { math, english }}) =>
console.log(id, name, math, english);
func(obj);
ES6 可直接在 parameter list 分解 nested object。
Function Return Object
let func = function() {
return {
firstName: 'Sam',
lastName: 'Xiao',
};
};
let result = func();
let firstName = result.firstName;
let lastName = result.lastName;
console.log(firstName, lastName);
若 function 回傳 object,要將 object 每個 property 指定到變數,在 ES5 會使用 .
的方式存取 property,需要 2 行。
let func = () => ({
firstName: 'Sam',
lastName: 'Xiao',
});
let { firstName, lastName } = func();
console.log(firstName, lastName);
ES6 可使用 object destructuring 接收 function 回傳的 object,會自動分解成變數。
let func = () => ({
firstName: 'Sam',
lastName: 'Xiao',
});
let { firstName } = func();
firstName; // ?
若並不想分解 function 所傳回的全部 property,可在 {}
寫要分解的變數即可。
let func = () => ({
firstName: 'Sam',
lastName: 'Xiao',
age: 20,
gender: 'Male',
});
let { firstName, lastName, ...info } = func();
console.log(firstName, lastName);
console.log(info);
若 function 回傳的 object,想部分也分解成 object,可搭配 ...
spread operator。
但這種寫法必須寫在 object destructuring 的最後才行
Conclusion
- Object destructing 的基本精神就是
一個蘿蔔一個坑
,ES6 會自動將 object 的 property 分解到變數 :
左側為 property,右側為新的變數名稱,可搭配=
設定 default value- Object destruncturing 配合 spread operator,可以取代原本
Object.assign()
才能複製 object - Object destructuring 配合 function parameter 特別好用,可以直接在 parameter list 中就分解 parameter,還可搭配 default value
- Object destructuring 可將 function 回傳的 object 直接分解到變數
Reference
MDN, Destructuring assignment
Glad Chinda, ES6 Destructuring: The Complete Guide