es6 解构用法:对 object 和 array 解构
参考文档:《Understanding ECMAScript 6》《深入理解ES6》
https://book.douban.com/subject/26864806/ (英文版+中文版)
解构目的:为了使代码更简单、简洁
解构对象:object 和 array
【注意】
- 针对对象和数组,使用语法不同。
- 一定要注意同样的符号出现在 = 左边和右边是不同的含义!!
- 解构时必须初始化(let, var, const),否则会报语法错误。
- object通过属性名访问对象,所以解构时用属性名作为新变量名;数组通过索引访问,所以解构时也只和索引位置有关。
- 解构对象时:
- 原有属性可设置别名,但不可设置默认值(设置了不报错也不启用默认值)
- 嵌套解构只新建最内层{ }中的属性名
- 冒号后面有{ } 是内层解构,冒号后面直接是变量名字则是别名
- 解构数组时:
- 设置的默认值只有指定位置的变量不存在或其值未定义时才起效
- 嵌套解构时 = 左边 [ ] 中的变量都存在,但都是单个的值
- 用扩展运算符... 可以把剩余的值都放到一个变量中,但这个变量在解构中必须是最后一个变量
一、 对象解构
1.1 基础用法
= 左边用 var, let 或 const 声明,然后一个 { } 包裹要新建的局部变量; = 右边是原始的对象。
左边用 { } 括起来是解构对象的语法,可以简单理解为右边是对象,所以左边也要是对象。
let node = { type: "Identifier", name: "foo" }; //因为右边是对象,所以左边也要是对象,所以用{}括起来,里面的type、name是原始变量的属性 let { type, name } = node; console.log(type); // "Identifier" console.log(name); // "foo"
单独的属性变量已经被定义后,想修改为原始对象的初始值:
type and name are initialized with values when declared, and then two variables with the same names are initialized with different values.
圆括号()让代码块变成表达式,表达式的值是 = 右侧的值。对象解构重新赋值时一定要加圆括号(),数组解构重新赋值不用加圆括号()
let node = { type: "Identifier", name: "foo" },
// change the values of variables after they’re defined, type = "Literal", name = 5; // assign different values using destructuring ({ type, name } = node); console.log(type); // "Identifier" console.log(name); // "foo"
1.2 解构设置默认值(原有属性不可设置默认值,只有新属性才变量会使用默认值,因为新属性变量时原始对象中不存在的属性)
如果 = 左边有原始对象没有的属性名,则默认赋 undefined ,设置了默认值则为默认值。
let node = { type: "Identifier", name: "foo" }; let { type, name, value } = node;//value不设置默认值就是 undefined console.log(type); // "Identifier" console.log(name); // "foo" console.log(value); // undefined
-- 给新属性赋值和设置默认值 let node = { type: "Identifier", name: "foo" }; let { type, name, value = true } = node; console.log(type); // "Identifier" console.log(name); // "foo" console.log(value); // true
【注意】原有属性可设置别名,但不可设置默认值。(设置了不会报错,但也不会使用默认值,而是使用从解构获取的对象中的值)
When you use a destructuring assignment statement and you specify a local variable with a property name that doesn’t exist on the object, that local variable is assigned a value of undefined.
You can optionally define a default value to use when a specified property doesn’t exist.
let node = { type: "Identifier", name: "foo" }; let { type, name } = node; console.log(type); // "Identifier" console.log(name); // "foo"
let node = { type: "Identifier", name: "foo" }; // 给原有属性设置默认值无效,因为其值不是 null 或 undefined let { type, name="new name" } = node; console.log(type); // "Identifier" console.log(name); // "foo"
1.3 给原对象中属性起别名
let node = { type: "Identifier" }; // {原属性:别名} let { type: localType, name: localName = "bar" } = node; console.log(localType); // "Identifier" console.log(localName); // "bar"
1.4 嵌套解构
let node = { type: "Identifier", name: "foo", loc: { start: { line: 1, column: 1 }, end: { line: 1, column: 4 } } };
针对上面这个嵌套的对象,可以使用嵌套解构,但要注意:最后新建的本地变量只有最内层解构,外侧的loc变量并不存在!!
冒号后面有{ } 是内层解构,冒号后面直接是变量名字则是别名。
// 此时loc变量不存在,存在的是start变量(解构出的变量是最内层{}) let { loc: { start }} = node; console.log(start.line); // 1 console.log(start.column); // 1
console.log(loc); // 报错 Uncaught ReferenceError: loc is not defined
嵌套解构使用别名:
// 冒号后面有{}是内层解构,冒号后面直接是变量名字则是别名 let { loc: { start: localStart }} = node; console.log(localStart.line); // 1 console.log(localStart.column); // 1
二、数组解构
2.1 基础用法
= 左边用 var, let 或 const 声明,然后一个 [ ] 包裹要新建的局部变量; = 右边是原始数组。
左边用 [ ] 括起来是解构数组的语法,可以简单理解为右边是数组,所以左边也要是数组。
let colors = [ "red", "green", "blue" ]; // Those values are chosen because of their position in the array; // the actual variable names could be anything. let [ firstColor, secondColor ] = colors; console.log(firstColor); // "red" console.log(secondColor); // "green"
// 只要第三个位置的元素值 let colors = [ "red", "green", "blue" ]; let [ , , thirdColor ] = colors; console.log(thirdColor); // "blue"
单独的变量已经被定义后,想修改为原始数组的初始值:
// 通过解构获得原始数组的值(无需圆括号()) let colors = [ "red", "green", "blue" ], firstColor = "black", secondColor = "purple"; // The only difference is that firstColor and secondColor have already been defined. [ firstColor, secondColor ] = colors; // 数组解构时无需圆括号,对象解构时需要圆括号 console.log(firstColor); // "red" console.log(secondColor); // "green"
2.2 数组解构的妙用:交换变量值
// swapping variables in ECMAScript 6 let a = 1, b = 2; // [] 在等号左边是解构,[]在等号右边是数组 // 一定要注意同样的符号出现在 = 左边和右边是不同的含义!! // 解构,第一位置的变量值等于右边数组中索引为0的值,即 已定义的变量a被赋值为[b,a]数组i=0的值,也就是b // 同理,变量b被重新赋值为i=1的数组值a [ a, b ] = [ b, a ]; console.log(a); // 2 console.log(b); // 1
2.3 解构时设置默认值
只有当指定位置的属性不存在或其值未定义时,才会使用默认值。
let colors = [ "red" ]; // Array destructuring assignment allows you to specify a default value for any position in the array, too.
// The default value is used when the property at the given position either doesn’t exist or has the value undefined . let [ firstColor, secondColor = "green" ] = colors; console.log(firstColor); // "red" console.log(secondColor); // "green"
2.4 嵌套解构
外层解构的新变量也存在,但只会按照索引位置取一个值而不是数组,如果想让最后一个变量是数组,需要使用扩展运算符...
Rest items use the ... syntax to assign the remaining items in an array to a particular variable.
let colors = [ "red", [ "green", "lightgreen" ], "blue" ]; // later let [ firstColor, [ secondColor ] ] = colors; console.log(firstColor); // "red" console.log(secondColor); // "green"
使用扩展运算符... 必须是最后一个变量,且后面不能有逗号
let colors = [ "red", "green", "blue" ]; let [ firstColor, ...restColors ] = colors;//restColors 是数组 console.log(firstColor); // "red" console.log(restColors.length); // 2 console.log(restColors[0]); // "green" console.log(restColors[1]); // "blue"
三、混合解构
let node = { type: "Identifier", name: "foo", loc: { start: { line: 1, column: 1 }, end: { line: 1, column: 4 } }, range: [0, 3] }; let { loc: { start }, range: [ startIndex ] } = node; console.log(start.line); // 1 console.log(start.column); // 1 console.log(startIndex); // 0
我觉得这样太复杂了,不过书上写这样十分有效,因为不用遍历整个json结构了。。
This approach is particularly useful for pulling values out of JSON configuration structures without navigating the entire structure.