學習 ECMAScript/JavaScript 6 - Destructuring
在 JavaScript 的設計場景中,我們使用了大量的陣列內容與屬性值操作。甚至在定義函數時也會使用屬性表作為參數,以換取選用性參數與擴充參數項目的彈性。例如:
function func1(props) {
if (props.width && props.height)
set_size(props.width, props.height);
if (props.x && props.y)
set_pos(props.x, props.y);
}
func1({width:100, height:50});
為了簡化陣列內容與屬性值的操作, ES6 新增了 Destructuring (解構) 語法。 Destructuring 的用法簡單地說就是左值(等號左邊的對象)可以放一組由變數組成的結構,由 ES6 將右值的陣列內容指派給左值的每個變數。
在 ES 的語法中, []
就代表配置一個陣列,{}
就代表配置一個標準個體 (standard object)。此兩者都是一種結構。依設計者使用的結構, ES6 的 Destructuring 敘述也有些差別。
解構陣列或迭代器
按照 Destructuring 的做法,當設計者要為多個變數賦值時,可以把這些變數放進一個陣列,再把這個陣列放在等號左邊。至於要指派的值,則用陣列與迭代器放在等號右邊。 ES6 就會解開兩邊的結構,將它擴展為多次賦值操作。設計者就不需要寫那麼多行賦值敘述了。如下所示:
// I want assign value to x and y.
var [x, y] = [1, 2];
// destructure to
var x = 1;
var y = 2;
ES6 還允許兩邊結構的項目數量不一致,或者左值的結構項目可以放空位跳過用不到的內容。當右值的項目數量少於左值時,不足的部份之預設值為 undefined,或者設為你指定的預設值。
// 右值少於左值
var [x, y, z] = [1, 2];
// destructure to
var x = 1;
var y = 2;
var z = undefined;
// 右值少於左值,但左值有設定預設值
var [x, y, z = 100] = [1, 2];
// destructure to
var x = 1;
var y = 2;
var z = 100;
// 左值少於右值
var [x, y] = [1,2,3];
// destructure to
var x = 1;
var y = 2;
// 左值放空位 (第二位放空)
var [x, ,y] = [1, 2, 3];
// destructure to
var x = 1;
var y = 3;
Undefined offset錯誤。 Python 要求兩邊的項目數量必須一致,多或少都視為 ValueError 例外。至於放空位的做法,Python 是技巧性地使用 _ 變數達成。
list($x, , $y) = [1, 2, 3];
x, _, y = [1, 2, 3]
ES6 也允許你用多層結構或 Rest parameters 。
var [x, y, [a,b,c]] = [1, 2, [10,11,12]];
var [x, ...y] = [1, 2, 3]
// destructure to
var x = 1;
var y = [2,3];
解構個體屬性
上節範例都是用陣列結構。若是操作屬性結構,你必須改用 {}
。ES6 解構時,將會按照屬性名稱賦值。沒有對應的屬性名稱的左值項目,則指派為 undefined 或設計者指定的預設值。
var {x, y, z} = {h:1, w: 2, x:100, y:200};
// destructure to
var x = 100;
var y = 200;
var z = undefined;
當你的左值是一個屬性結構時,ES6 的解構行為是走訪屬性。所以右值雖然可以放陣列,但基本上沒有作用。下例給各位一個思考空間:
var {x, length} = [10, 20];
console.log(x); // undefined
console.log(length); // 2; 因為陣列一定有表示長度的屬性 length ,而 [10,20] 這個陣列的長度是 2 。
應用情境
通常我們會將解構語法用於接收函數回傳值是陣列時。如下:
function get_image_size() {
// do something...
return [w, h, x, y];
}
// without destructuring:
var result = get_image_size();
var width = result[0];
var height = result[1];
// with destructuring:
var [width, height] = get_image_size();
for-of 也是解構語法的常用場合。例如 ES6 新增的集合型態 Map 每次迭代回傳的值都是一組 [key, value]
結構,所以 for-of 時可以用解構語法將迭代結果分別指派給兩個變數。如下:
var map = new Map();
map.set('a', 1);
map.set('b', 2);
for (let [k, v] of map) { // [k, v] = [key, value]
console.log(k, ' => ', v);
}
// without destructuring
for (let v of map) {
console.log(v[0], ' => ', v[1]); // 可讀性差了許多
}
Destructuring 是一個語法糖衣。介紹到此也就差不多了。
相關文章
- ES6 In Depth: Destructuring
- Functional enhancements in ECMAScript 6
- Variable declarations and more in the new JavaScript
- 石頭閒語: ECMAScript/JavaScript 6 - Template strings
- 石頭閒語: ECMAScript/JavaScript 6 - Symbol
- 石頭閒語: ECMAScript/JavaScript 6 - for-of 與 iterator。
- 石頭閒語: ECMAScript/JavaScript 6 - Generator
- 石頭閒語: ECMAScript/JavaScript 6 - 新函數語法 - Arrow functions, Rest and Spread parameters, Default value
- 石頭閒語: ECMAScript/JavaScript 6 - Destructuring
- 石頭閒語: ECMAScript/JavaScript 6 - var, let 和 const
- 石頭閒語: ECMAScript/JavaScript 6 - Proxy 和 Reflect
- 石頭閒語: ECMAScript/JavaScript 6 - Class
- 石頭閒語: ECMAScript/JavaScript 6 - 語法補遺
- 石頭閒語: ECMAScript/JavaScript 6 - Promise