详解解构赋值

283 阅读4分钟

解构赋值是一种用来将数据结构(如数组、对象、Set、Map等)中的值提取出来并赋值给变量的语法。

语法

解构赋值的语法包括两个部分:解构的模式和赋值的表达式。解构的模式指定了需要提取的值的结构,可以是数组、对象、Set、Map等。赋值的表达式则指定了需要将提取出来的值赋给哪些变量。解构赋值的基本语法如下:

数组解构赋值

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

上面的代码将数组 [1, 2, 3] 解构成三个变量 abc,并分别赋值为 123。这相当于如下的赋值语句:

let a = 1;
let b = 2;
let c = 3;

如果数组中的元素不足以提供所有的变量,那么没有对应的变量将被赋值为 undefined

对象解构赋值

let {name, age} = {name: 'Alice', age: 30};

上面的代码将对象 {name: 'Alice', age: 30} 解构成两个变量 nameage,并分别赋值为 'Alice'30。这相当于如下的赋值语句:

let name = 'Alice';
let age = 30;

如果需要使用不同的变量名来访问对象属性,可以使用“键值对”的语法来指定变量名和属性名的对应关系。

let {name: n, age: a} = {name: 'Alice', age: 30};

上面的代码将对象 {name: 'Alice', age: 30} 解构成两个变量 na,并分别赋值为 'Alice'30

嵌套解构赋值

解构赋值也可以用来提取嵌套数据结构中的值。例如:

let {name, age, address: {city, street}} = {
  name: 'Alice',
  age: 30,
  address: {
    city: 'Shanghai',
    street: 'Nanjing Road'
  }
};

上面的代码将对象 {name: 'Alice', age: 30, address: {city: 'Shanghai', street: 'Nanjing Road'}} 解构成三个变量 nameagecitystreet。其中,address 是一个嵌套对象,可以使用 address: {city, street} 的语法来提取其中的属性。最终的结果是:

let name = 'Alice';
let age = 30;
let city = 'Shanghai';
let street = 'Nanjing Road';

Set 和 Map 解构赋值

除了数组和对象之外,Set 和 Map 也支持解构赋值。

对于 Set,解构赋值将从 Set 中按顺序提取元素,并赋值给对应的变量。例如:

let set = new Set(['red', 'green', 'blue']);
let [a, b, c] = set;

上面的代码将 Set {red, green, blue} 解构成三个变量 abc,并分别赋值为 'red''green''blue'

对于 Map,解构赋值将从 Map 中按顺序提取键值对,并将键和值分别赋值给对应的变量。例如:

let map = new Map([['name', 'Alice'], ['age', 30]]);
let [[k1, v1], [k2, v2]] = map;

上面的代码将 Map {name => 'Alice', age => 30} 解构成四个变量 k1v1k2v2,并分别赋值为 'name''Alice''age'30'。这里需要注意的是,Map 中的键值对也是一个数组,因此需要使用两层解构。

用法

交换变量的值

解构赋值可以用来快速交换两个变量的值,而不需要使用临时变量。例如:

let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1

上面的代码交换了变量 ab 的值,不需要使用临时变量。

从函数返回多个值

函数只能返回一个值,但是使用解构赋值可以返回多个值。例如:

function getData() {
  return [1, 2, 3];
}

let [a, b, c] = getData();
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3

上面的代码从函数中返回了三个值,然后使用解构赋值将这三个值分别赋值给变量 abc。这样做的好处是可以在一次函数调用中获取多个值,而不需要使用多个变量来接收这些值。

提取函数参数中的属性

在函数的参数中可以使用解构赋值来提取对象中的属性。例如:

function printUser({name, age, address}) {
  console.log(`${name} (${age}) - ${address.city}, ${address.street}`);
}

let user = {
  name: 'Alice',
  age: 30,
  address: {
    city: 'Shanghai',
    street: 'Nanjing Road'
  }
};

printUser(user);
// 输出:Alice (30) - Shanghai, Nanjing Road

上面的代码定义了一个函数 printUser,它的参数是一个对象,其中包含了用户的姓名、年龄和地址。使用解构赋值将这些属性分别赋值给变量 nameageaddress,然后打印出用户的信息。

简化对象的写法

在创建对象时,可以使用解构赋值来简化属性的写法。例如:

let name = 'Alice';
let age = 30;
let address = {
  city: 'Shanghai',
  street: 'Nanjing Road'
};

let user = {name, age, address};
console.log(user);
// 输出:{name: 'Alice', age: 30, address: {city: 'Shanghai', street: 'Nanjing Road'}}

上面的代码将变量 nameageaddress 分别赋值给对象 user 的同名属性,从而简化了对象的写法。

接收剩余的元素

解构赋值可以使用扩展运算符 ... 来接收剩余的元素。例如:

let [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a); // 1
console.log(b); // 2
console.log(rest); // [3, 4, 5]

上面的代码使用解构赋值将数组 [1, 2, 3, 4, 5] 分别赋值给变量 abrest。由于 rest 前面使用了扩展运算符 ...,因此它会接收数组中剩余的元素,并将它们放入一个新数组中。

默认值

解构赋值可以给变量设置默认值,当被赋值的值为 undefined 时,会使用默认值。例如:

let {name = 'Anonymous', age = 18} = {name: 'Alice'};

console.log(name); // Alice
console.log