javascript - 变量的解构赋值

A:什么是解构赋值?
Q:ES6允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这就是解构。

模式匹配:

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

// 相当于
let a = 1;
let b = 2;
let c = 3;

只要等号两边的模式相同,左边的变量就会被赋值给对应的值。


1. 数组的解构赋值

1.1 基本用法

  • 变量取值由它的位置决定
let [x, [[y], z]] = [1, [[2], 3]];

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

x // 1
y // 3
// ... 剩余操作符,把剩余的内容赋值给y
let [x, ...y] = [1, 2, 3];

x // 1
y // [2, 3]
  • 解构不成功的时候会返回undefined
let [x, y, ...z] = ['a'];

x // 'a'
y // undefined
z // []
  • 不完全解构,但可以解构成功
let [x, y] = [1, 2, 3];

x // 1
y // 2
  • 等号右边不是数组会报错
// error
let [x] = 1;
let [x] = true;
let [x] = NaN;
let [x] = undefined;
let [x] = null;
let [x] = {};
  • 对于Set解构,可以使用解构赋值
let [x, y, z] = new Set(['a', 'b', 'c']);

x // 'a'

如果某种数据结构具有Iterator接口,就可以采用数组形式进行解构赋值。

1.2 默认值

解构赋值允许指定默认值。

let [x = true] = [];

x // true
  • ES6内部使用严格相等运算符(===)判断一个位置是否有值
  • 如果一个数组成员不严格等于undefined,则默认值不生效
let [x, y = 'b'] = ['a'];

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

x // 'a'
y // 'b'

(相等运算符:https://blog.csdn.net/qq_46025031/article/details/114938271

let [x = 1] = [undefined];

x // 1
// 数组中的undefined严格等于undefined,默认值生效
let [x = 1] = [null];

x // null
// 数组中的null不严格等于undefined,默认值不生效
  • 惰性求值:如果默认值为表达式,则表达式是惰性求值的,用到的时候才会求值。
function f() {
	console.log(222);
}

let [x = f()] = [1];

x // 1

因为x能取到值,所以f()不会执行。

  • 默认值可以引用其他解构赋值的变量
let [x = 1, y = x] = []  // x = 1, y = 1
let [x = 1, y = x] = [2]  // x = 2, y = 2
let [x = 1, y = x] = [1, 2]  // x = 1, y = 2
let [x = y, y = 1] = []  // error,x用到默认值y时y还没有声明

2. 对象的解构赋值

  • 变量必须与属性同名才能取到正确的值
let {a, b, c} = {a: 'aaa', b: 'bbb'};

a // aaa
b // bbb
c // undefined
  • 变量名与属性名不一致
let {a: c} = {a: 'aaa', b: 'bbb'};

c // aaa
  • 对象的解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量。真正被赋值的是后者,而非前者。
let {a: c} = {a: 'aaa', b: 'bbb'};

c // aaa
a // error
// a 是匹配的模式,c 才是变量
  • 嵌套结构
let obj = {
	p: [
		'hello',
		{y: 'world'}
	]
}

let {p: [x, {y}]} = obj;

// p为模式
x // 'hello'
y // 'world'

// 如果想给p赋值
let {p, p: [x, {y}]} = obj;

p // ['hello', {y: 'world'}]
  • 指定默认值
let {x = 3} = {x: undefined};

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

x // null
  • 解构失败
let {a} = {b: 'bbb'};

a // undefined

3. 字符串的解构赋值

let [a, b, c, d, e] = 'hello';

a // 'h'
b // 'e'
...
  • length属性
let {length: len} = 'hello';

len // 5

4. 数值和布尔值的解构赋值

  • 如果等号右边是数值和布尔值,会先转为对象
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
  • undefined 和 null 无法转为对象,解构时会报错
let {prop: x} = undefined; // error
let {prop: y} = null; // error

5. 函数参数的解构赋值

function f({x = 0, y = 0} = {}) {
	return [x, y];
}

f({x: 3, y: 8}); // [3, 8]
f({x: 3}); // [3, 0]
f({}); // [0, 0]
f(); // [0, 0]

6. 圆括号问题

6.1 不能使用圆括号的情况

  1. 变量声明语句
let [(a)] = [1]; // error

let {x: (c)} = {}; // error
  1. 函数参数
function f([(z)]) {
	return z;
} // error
  1. 赋值语句的模式
// 整个模式放在圆括号中,报错
({p: a}) = {p: 12};
([a]) = [5];
// 部分模式放在圆括号中,报错
[({p: a}), {x: c}] = [{}, {}];

6.2 可以使用圆括号的情况

赋值语句的非模式部分可以使用圆括号。

[(b)] = [3];

({p: (d)} = {});

[(parseInt.prop)] = [3];

7. 用途

  1. 交换变量的值
  2. 从函数返回多个值
  3. 函数参数的定义
  4. 提取JSON数据
  5. 函数参数的默认值
  6. 遍历Map结构
  7. 输入模块的指定方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值