I. Objective
Extract values from objects or arrays and assign to other variables, previously had to do this:
var arr = [1, 2, 3, 4];
var first = arr[0];
var senond = arr[1];
var third = arr[3];
Decompose array to get element values, and assign. The above process is: destructuring-assignment
ES6 proposes new concept: destructuring (destructuring assignment), can make the above process have better readability, avoid code like "hard-coding" style
II. iterable Destructuring
var/let/const [var1, var2...] = iterable syntax indicates declaring variables while performing array/iterator destructuring assignment
Destructured value must be iterable, can conveniently make custom objects become iterable through generator syntax (see [An Yu Qing Yang: for...of Loop_ES6 Notes 1](/articles/for-of 循环-es6 笔记 1/#articleHeader5)), iterable destructuring features are as follows:
-
Can destructure arbitrarily deep nested arrays
-
Can leave empty positions to skip certain elements
-
Can use rest parameters (
...varsyntax, details please check [An Yu Qing Yang: Default Parameters and Rest Parameters_ES6 Notes 4](/articles/默认参数和不定参数-es6 笔记 4/)) to capture all remaining elements
For example:
// Array
var [[first, [second]], third] = [[1, [2]], 4];
console.log(`first = ${first}`); // 1
console.log(`second = ${second}`); // 2
console.log(`third = ${third}`); // 4
// iterable
var iter = (function*(start) {
while (true) {
yield start++;
}
})(0);
var [v1, v2, v3, v4] = iter;
console.log(`v1 = ${v1}`); // 0
console.log(`v2 = ${v2}`); // 1
console.log(`v3 = ${v3}`); // 2
console.log(`v4 = ${v4}`); // 3
// Skip elements, capture remaining elements
var arr = [1, 2, 3, 4];
var [, sec, ...aRest] = arr;
console.log(`sec = ${sec}`); // 2
console.log(`aRest = ${aRest}`); // [3, 4]
Code like "hard-coding" style is all gone, and destructuring assignment is more clear and intuitive (left-right correspondence)
III. Object Destructuring
var/let/const {key: varName, ...} = obj syntax indicates object destructuring
Special note: Assignment order is from left to right, actual effect is: varName = obj[key]
Destructured value must be able to be forcibly converted to object, so destructuring undefined/null will report error TypeError
Object destructuring features are as follows:
-
When variable name is consistent with object property name can be abbreviated
-
Can only assign to specific property names (no need to leave empty positions to skip)
-
Supports complex nesting (object+array)
For example:
// obj
var obj = {name: 'aae', age: 12, sex: 'F'};
// Only assign to specific property names
var {name: mName, sex: mSex} = obj;
console.log(`mName = ${mName}`); // mName = aae
console.log(`mSex = ${mSex}`); // mSex = F
// Abbreviate when variable name is same as property name
var {name, sex} = obj;
console.log(`name = ${name}`); // name = aae
console.log(`sex = ${sex}`); // sex = F
Note, if destructuring assignment left side has no var/let/const (i.e. forgot to declare variable, or variable already exists and don't want to declare again), will cause syntax error, as follows:
// var key;
{key} = {key: 'val'};
// Error: Uncaught SyntaxError: Unexpected token =(…)
Because {key} on left side of assignment will be parsed as a block ({}), solution to avoid this behavior is add parentheses around destructuring assignment, for example:
({key} = {key: 'val'});
console.log(`key = ${key}`); // key = val
Everything inside parentheses are expressions, {key} won't be misparsed as block
IV. Destructuring While Setting Default Values
Syntax similar to default parameter syntax, for example:
// default val
var [val = 'default val'] = [];
var {key: val = 'default val'} = {};
// When property names are same can abbreviate to
// FF43, 45 both don't support, thinkjs, Chrome50 support
// var {val = 'default val'} = {};
console.log(`val = ${val}`);
One statement both sets default value, and destructuring assignment, but syntax is somewhat difficult to read in more complex cases (such as above var {key: val = 'default val'} = {};)
V. Summary
This feature also belongs to icing on the cake things, reduces code like "hard-coding" style, enhances its readability
Uses:
-
Object parameters in function definitions, such as
function ajax(config), after changing tofunction ajax({url, data, callback})API readability is better, very convenient with default values (avoids operations likevar attr = config.attr || defultVal;) -
Cooperate with iterators, very convenient to traverse map ([key, val] traverse key-value pairs, [key] traverse key set, [, val] traverse value set)
-
Implement functions returning multiple values (return array, destructure into individual variables when accepting return value)
-
Import part of CommonJS modules, only destructure the parts needed. ES6 module import supports similar functionality
For example:
// use
// 1
function ajax({url, data, callback}) {
console.log(`ajax(${url}, ${data}, ${callback})`);
}
ajax({url: 'www.xxx.xx', data: 'data'});
// log print: ajax(www.xxx.xx, data, undefined)
// 2
for (var [key, val] of new Map([['name', 'eea'], ['age', 12]])) {
console.log(`key = ${key}, val = ${val}`);
}
// log print: key = name, val = eea
// key = age, val = 12
// 3
var [res1, res2] = (function() {
return [1, {a: 1}];
})();
console.log(`res1 = ${res1}, res2 = ${res2}`);
// res1 = 1, res2 = [object Object]
Reference Materials
- "ES6 in Depth": Free e-book provided by InfoQ Chinese site
No comments yet. Be the first to share your thoughts.