ES6之解构赋值

78 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

字符串

const [a, b, c] = '吴小白';
a; // "吴"
b; // "小"
c; // "白"

字符串还有 length属性,可以对它进行解构赋值

let { length: len } = '吴小白';
len; // 3

数组

用法

左边的变量会按顺序被赋予对应的值

let [a, b, c] = [1, 2, 3];

多层嵌套的数组解构

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo; // 1
bar; // 2
baz; // 3

不完全解构

let [x, , y] = [1, 2, 3];
x; // 1
y; // 3

let [x, y, z] = [1, [2, 2.1], 3];
x; // 1
y; // 2
z; // 3

解构不成功,变量的值就等于undefined

let [x, y, ...z] = ['a'];
x; // "a"
y; // undefined
z; // []
let [x, ...y] = [1, 2, 3, 4];
x; // "a"
y; // [2, 3, 4]

对于 Set 结构,也可以使用数组的解构赋值。

let [x, y, z] = new Set(['a', 'b', 'c']);
x; // 'a'
y; // 'b'
z; // 'c'

只要某种数据结构具有 Iterator(遍历器) 接口,都可以采用数组形式的解构赋值。

设置默认值

let [foo = true] = [];
foo; // true

let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
let [x = 1] = [undefined];
x; // 1

let [x = 1] = [null];
x; // null

对象

用法

与数组不同的是,对象的属性没有顺序的,因此变量必须与属性同名,才能取到正确的值。

let { foo, bar, baz } = { foo: 'a', bar: 'b' };
foo; // "a"
bar; // "b"
baz; // undefined

上面的代码 baz 没有对应的属性名导致取不到值,因此是 undefined

万一这个 key 值已经在别的地方使用了,这里会重复怎么办?不要担心,这里可以使用别名。

let { foo: f, bar: b, baz } = { foo: 'a', bar: 'b' };
f; // "a"
b; // "b"
baz; // undefined

这是不是说明了实际应该是这样子的

let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };

先找到对应的 key ,然后才进行的复制操作,所以真正被赋值的是 f, 而不是 foo, foo只是用来匹配的。

嵌套赋值

let obj1 = {
  p: ['Hello', { y: 'World' }],
};
let {
  p: [x, { y }],
} = obj1;
x; // "Hello"
y; // "World"

let obj2 = {};
let arr = [];

({ foo: obj2.prop, bar: arr[0] } = { foo: 123, bar: true });

obj2; // {prop:123}
arr; // [true]

如果结构时候子对象所在的父属性里面没有就会报错。所以在对象的解构的时候一定要注意父属性里面是否有对应的 key

let {
  foo: { bar },
} = { baz: '1' };
// Cannot read properties of undefined (reading 'bar')

设置默认值

let { x = 1 } = {};
x; // 1

let { x, y = 22 } = { x: 2 };
x; // 2
y; // 22

let { x: y = 3 } = {};
y; // 3

let { x: y = 3 } = { x: 4 };
y; // 4

函数参数

用法

function add([a, b]) {
  return a + b;
}

add([1, 2]); // 3

数组参数就被解构成变量ab

[
  [1, 2],
  [3, 4],
].map(([a, b]) => a + b);
// [3, 7]

使用默认值

function log({ x = 0, y = 0 } = {}) {
  console.log(x, y);
}

log({ x: 6, y: 8 }); // 6, 8
log({ x: 6 }); // 6, 0
log({}); // 0, 0
log(); // 0, 0

还有一种情况

function log({ x, y } = { x: 0, y: 0 }) {
  console.log(x, y);
}

log({ x: 3, y: 8 }); // 3, 8
log({ x: 3 }); // 3, undefined
log({}); // undefined, undefined
log(); // 0, 0

第一种写法,为函数log的参数的变量指定默认值

第二种写法,为函数log的参数指定默认值,而不是为变量xy指定默认值

数值和布尔值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

let { toString: s } = 123;
s === Number.prototype.toString; // true

let { toString: s } = true;
s === Boolean.prototype.toString; // true

数值和布尔值的包装对象都有toString属性,因此变量 s 都能取到值。

如果等号右边的值不是对象或数组,就先将其转为对象。由于undefinednull无法转为对象,所以对它们进行解构赋值,都会报错。

let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError