ES6 解构赋值详解:数组、对象与常见应用场景

作者:闭包旅人

时间:2026-10-24

浏览:438

本文深入解析 ECMAScript 2015 引入的解构赋值语法,涵盖数组与对象的模式匹配机制。详细讲解完全与不完全解构、默认值生效条件(全等于 undefined)、函数参数定义及变量交换等实用场景,并指出小括号使用的限制与规范,帮助开发者编写更简洁高效的现代 JavaScript 代码。

文章目录

1. 数组的解构赋值

1.1 数组解构赋值的概念

在 ECMAScript 2015 标准中,允许按照特定的模式,从数组和对象中提取值,并对变量进行赋值,这一机制被称为解构赋值。

在 ECMAScript 2015 标准发布之前,为变量赋值的方式通常如下所示:


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


而在 ECMAScript 2015 标准中,上述赋值可以简化为以下写法。


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


ECMAScript 2015 的解构赋值本质上属于模式匹配。当赋值运算符两边的模式相同时,左侧的变量会被赋予对应位置的值。

1.2 数组解构赋值失败的情况

如果解构赋值失败,变量的值将等于 undefined。示例代码如下所示:


// 如果数组的某个索引值的位置的变量,在 = 运算符的右边没有数组中没有对应的索引值与之对应,则解耦赋值失败,其值为 undefined
let [v] = []
let [a, b] = [1]
console.log(v, a, b); // undefined 1, undefined


若要解决解构赋值失败的问题,需要确保赋值运算符左右两边的元素数量保持一致。

1.3 不完全解构赋值

所谓的不完全解构赋值,是指赋值运算符右侧数组中的元素数量大于左侧变量的数量。这会导致右侧部分元素无法被提取,但在这种情况下,解构赋值操作依然会成功执行。

示例代码如下所示:


// 赋值运算符左边变量的数量小于右边值的数量
let [a, b, c] = [1, 2, 3, 4]  // 依然会解耦赋值成功
console.log(a, b, c); // 1 2 3


1.4 默认值的使用

解构赋值允许为变量指定默认值。示例代码如下所示:


/* 
 * 解耦赋值中允许指定默认值
 * 语法结构如下
 * let [var1 = value1, var2 = value2 ,...] = [val1, val2,...]
   var1,var2 表示变量名
   value1,value2 表示默认值
   val1,val2, 表示指定的值
 */
let [a = 1, b = 2] = [100]
console.log(a, b); // 100 2


在使用默认值时,有一个关键点需要注意:ECMAScript6 内部会使用全等于(===)运算符来判断指定位置的值是否全等于 undefined。只有当该位置的值严格等于 undefined 时,默认值才会生效。

测试代码如下所示:


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


当我们使用 null 值时,虽然 null 也表示为空,但是 null !== undefined。因此,在这种情况下默认值并不会生效。

测试代码如下:


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


1.5 数组解构赋值的复杂情况

由于 JavaScript 是一种弱类型语言,赋值号右侧可以是任何类型,因此会出现以下几种特殊情况:

情况一:运算符右侧是一个函数,示例代码如下:


// 1. 运算符右边是一个函数
let [a, b] = [1, function () {
  return 10;
}]
console.log(b()); // 10


情况二:运算符右侧是一个对象,示例代码如下:


// 2. 运算符右边是一个对象
let [a, b] = [1, {
  name: '狐妖小红娘'
}]
console.log(b); // { name: '狐妖小红娘' }


情况三:运算符右侧是含有数组的结构,示例代码如下:


// 3. 运算符右边是含有数组
let [a, b] = [1, [2, 3]]
console.log(b); // [ 2, 3 ]


情况四:运算符左右两边都含有数组,示例代码如下所示:


// 4. 运算符左右两边都含有数组,示例代码如下所示
let [a, [b, c]] = [1, [2, 3]]
console.log(b); // 2


2. 对象的解构赋值

对象的解构赋值是通过变量名称与对象的属性名称一一对应来实现的。示例代码如下所示:


/*
  * 对象的解耦赋值 - 从对象中提取值,为变量赋值
    ! 变量名称必须与对象的属性名称一一对应,否则就会导致失败。
*/
let {
  x,
  y
} = {
  x: 10,
  y: 20
}
console.log(x, y); //10 20


值得注意的是,赋值运算符两边的格式需要保持一致。

2.1 对象解构赋值的特殊情况

由于 JavaScript 是一个弱类型的语言,所以赋值号右侧可以是任何类型,那就会出现以下几种特殊情况:

情况一:运算符右侧是一个函数,示例代码如下:


// 1. 运算符右边是一个函数
let { a, b } = {
  a: 1,
  b: function () {
    return 10;
  }
}
console.log(b());// 10


情况二:运算符右侧是一个对象,示例代码如下:


// 2. 运算符右边是一个对象
let {a, b} = {
  a: 1,
  b: {
    name: 'ywanzhou'
  }
}
console.log(b); // { name: 'ywanzhou' }


情况三:运算符右侧是含有数组的结构,示例代码如下:


// 3. 运算符右边是含有数组
let {a, b} = {
  a: 1,
  b: [1, 2]
}
console.log(b); //[ 1, 2 ]


情况四:运算符左右两边都含有对象,示例代码如下所示:


// 4. 运算符左右两边都含有对象
let {
  m: {
    name,
    age
  },
  n
} = {
  m: {
    name: 'test',
    age: 20
  },
  n: 20
}
console.log(name, age); // test 20

2.2 解构赋值失败

如果解构赋值失败,变量的值等于 undefined。示例代码如下所示:


// 解耦赋值失败
let {
  a,
  b
} = {
  a: 10
}
console.log(b);


2.3 不完全解构赋值

所谓的不完全解构赋值,是指赋值运算符右侧对象中属性的数量大于左侧对象中属性的数量。这会导致右侧部分属性无法被提取,但在这种情况下,解构赋值依然会成功。


// 不完全解耦赋值
let {
  a
} = {
  a: 10,
  b: 20
}
console.log(a);


2.4 默认值

解构赋值允许指定默认值。示例代码如下所示:


// 默认值
let {
  a,
  b = 100
} = {
  a: 10,
  b: 20
}
console.log(b);


3. 字符串、数值和布尔值的解构赋值

3.1 字符串解构赋值

字符串也可以进行解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。


let [h1, y, x] = "一碗周"
console.log(h1, y, x, h2); // 一 碗 周


3.2 数值和布尔值的解构赋值

如果直接对数字值或布尔值进行解构赋值会抛出异常。在对数值和布尔值进行操作时,其赋值运算符右侧是数值和布尔值,则会先将其转为对象。


// let [a] = 100; // 抛出异常 描述信息为 TypeError: 100 is not iterable
// console.log(a);
// 对布尔或者数值进行解耦赋值的话, 需要现将其改变成为对象类型。
let {
  toString: b
} = 1;
console.log(b === Number.prototype.toString); // true

let {
  toString: c
} = true;
console.log(c === Boolean.prototype.toString); // true

解构赋值的规则是,只要等号右侧的值不是对象或数组,就先将其转为对象。由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值都会报错。

4. 函数的解构赋值

函数的参数也可以使用解构赋值。示例代码如下所示:


// 使用数组
function f([a, b]) {
  console.log(a, b);  
}
f([10, 20]) // 10 20
// 使用对象
function fn({
  a,
  b
}) {
  console.log(a, b);
}
fn({
  a: 10,
  b: 20
})  // 10 20


5. 小括号的问题

解构赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能确定。

由此带来的问题是,如果模式中出现小括号该如何处理。ECMAScript 2015 的规则是:只要有可能导致解构的歧义,就不得使用小括号。

但是,这条规则实际上不那么容易辨别,处理起来相当麻烦。因此,建议只要有可能,就不要在模式中放置小括号。

5.1 不能使用小括号的情况

如下三种情况不能使用小括号:

情况一:变量声明语句,示例代码如下所示:


// 如下情况全部会报错
let [(a)] = [1];

let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};

let { o: ({ p: p }) } = { o: { p: 2 } };

上面 6 个语句都会报错,因为它们都是变量声明语句,模式不能使用小括号。

情况二:作为函数参数

函数参数也属于变量声明,因此不能带有小括号。


// 报错
function f([(z)]) { return z; }
// 报错
function f([z,(x)]) { return x; }

情况三:赋值语句的模式


// 全部报错
({ p: a }) = { p: 42 };
([a]) = [5];


上面代码将整个模式放在小括号之中,导致报错。


// 报错
[({ p: a }), { x: c }] = [{}, {}];


上面代码将一部分模式放在小括号之中,导致报错。

5.2 可以使用小括号的情况

可以使用小括号的情况只有一种:赋值语句的非模式部分,可以使用小括号。


[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确

上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;其次它们的小括号都不属于模式的一部分。第一行语句中,模式是取数组的第一个成员,跟小括号无关;第二行语句中,模式是 p,而不是 d;第三行语句与第一行语句的性质一致。

6. 变量解构赋值的用处

变量解构赋值的用处有很多,下面举几个比较常见的例子。

6.1 交换变量的值

如果没有解构赋值,交换变量需要借助第三个变量才能完成,示例代码如下所示:


var a = 10,
  b = 20;

var c = a;
a = b
b = c
c = null  /// 释放变量
console.log(a, b); // 20 10


借助变量解构赋值完成,示例代码如下所示:


let a = 10,
  b = 20;
[a, b] = [b, a]
console.log(a, b); // 20 10


使用这种方式不仅简洁,而且易读,语义清晰。

6.2 从函数返回多个值

函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。

示例代码如下所示:


// 返回一个数组

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

6.3 函数参数的定义

解构赋值可以方便地将一组参数与变量名对应起来。


// 参数是一组有次序的值
function f([x, y, z]) {
  console.log(x, y, z);
}
f([1, 2, 3]);  // 1 2 3

// 参数是一组无次序的值
function fn({x,  y,  z}) {
  console.log(x, y, z);
}
fn({
  z: 3,
  y: 2,
  x: 1
});  // 1 2 3

6.4 提取 JSON 数据

解构赋值对提取 JSON 对象中的数据,尤其有用。


// 提取json数据
let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let {
  id,
  status,
  data: number
} = jsonData;

console.log(id, status, number); // 42, "OK", [867, 5309]

到此这篇关于 JS ES 新特性之变量的解构赋值的文章就介绍到这了,更多相关 ES 变量的解构赋值内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章