解构
数组解构
- 基本用法
let [a , b] = [1, 2] // a = 1 b = 2 let [a, b] = 1 // 报错 let [a, b] = [1] // a = 1 b = undefined let [a, b] = [1, null] // a = 1 b = null let [a, ...b] = [1, 2, 3, 4] // a = 1 b = [2, 3, 4] let [x, y, z] = new Set(['a', 'b', 'c']) // x = a y = b z = c
- 默认值
let [x = 1, y = x] = [2]; // x=2; y=2
对象解构
- 基本用法
let { bar, foo } = { foo: 'aaa', bar: 'bbb' }; // bar = bbb foo = aaa let { bar, foo } = { bar: 'bbb' }; // bar = bbb foo = undefined // let {bar, foo} 是 let {bar: bar, foo: foo} 的简写 真正赋给值的是:后的 // 例如 let { bar: foo } = { bar: 'bbb', foo: 'aaa'} // foo = bbb // 下面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; baz // "aaa" foo // error: foo is not defined
- 用于嵌套结构的对象
这时p是模式,不是变量,因此不会被赋值。如果p也要作为变量赋值,可以写成下面这样let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p: [x, { y }] } = obj; x // "Hello" y // "World"
如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p, p: [x, { y }] } = obj; x // "Hello" y // "World" p // ["Hello", {y: "World"}]
// 报错 let {foo: {bar}} = {baz: 'baz'};
- 对象的解构赋值可以取到继承的属性
上面代码中,对象obj1的原型对象是obj2。foo属性不是obj1自身的属性,而是继承自obj2的属性,解构赋值可以取到这个属性。const obj1 = {}; const obj2 = { foo: 'bar' }; Object.setPrototypeOf(obj1, obj2); const { foo } = obj1; foo // "bar"
- 默认值
let {x, y = 5} = {x: 1};
x // 1
y // 5
let {x: y = 3} = {};
y // 3
let {x: y = 3} = {x: 5};
y // 5
默认值生效的条件是,对象的属性值严格等于undefined。
let {x = 3} = {x: undefined};
x // 3
let {x = 3} = {x: null};
x // null
-
注意点
如果要将一个已经声明的变量用于解构赋值// 错误的写法 let x; {x} = {x: 1}; // SyntaxError: syntax error\ // 因为 JavaScript 引擎会将{x}理解成一个代码块,等号左边是不允许出现代码块语句的,从而发生语法错误 // 正确的写法 let x; ({x} = {x: 1});
由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构
let arr = [1, 2, 3]; let {0 : first, [arr.length - 1] : last} = arr; first // 1 last // 3
字符串的解构
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
let {length : len} = 'hello';
len // 5
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
数值和布尔值的包装对象都有toString属性,因此变量s都能取到值。
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
函数参数赋值解构
[[1, 2], [3, 4]].map(([a, b]) => a + b);
赋值默认值同上
圆括号问题
不可使用圆括号
- 声明语句(函数参数也是声明)
let ([a]) = [1] 或(let [a] = [1]) // 报错
- 括号包含了模式
({a: b}) = {a: 1}
{(a): b} = {a: 1}
使用圆括号
{a: (b)} = {a: 1}
({a: b} = {a: 1})
网友评论