JavaScript 知识篇(1):解构赋值
解构赋值是 ES6 引入的一种语法特性,它允许我们按照一定模式从数组或对象中提取值,然后对变量进行赋值。这种语法让我们的代码更加简洁、易读,同时提高了开发效率。本文将通过丰富的示例和实际应用场景,带你全面掌握ES6解构赋值的精髓。
一、数组解构
1.1 基本用法
我们先来看一下传统用法,以前,为变量赋值,只能直接指定值。
const arr = [1, 2, 3];
const a = arr[0];
const b = arr[1];
const c = arr[2];
再来看一下解构赋值方式,代码表示,可以从数组中提取值,按照对应位置,对变量赋值。
本质上,这种写法属于 模式匹配 ,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
let arr = [1, 2, 3]
let [a, b, c] = arr
console.log(a,b,c) // 1,2,3
这样是不是能很直观的看出来解构赋值的方便之处?
下面还有一些例子我们可以看一下
// 跳过某些元素
let [first, , third] = [1, 2, 3, 4];
console.log(first, third); // 1 3
// 嵌套 (记住模式匹配,如果模式不匹配则会解构失败)
let [foo, [[bar], baz]] = [1, [[2], 3]];
1.2 默认值
解构赋值允许指定默认值。
let [a = 1, b = 2] = [10];
console.log(a, b); // 10 2let [x, y = 5] = [1, undefined];
console.log(x, y); // 1 5
注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined
,默认值才会生效。
let [x = 1] = [undefined];
x // 1let [x = 1] = [null];
x // null
上面代码中,如果一个数组成员是null
,默认值就不会生效,因为null
不严格等于undefined
。
1.3 剩余模式与交换变量
一个数组当中,如果我们只想要前两个,后面的不需要我们该如何做呢?
// 剩余模式
let [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a, b, rest); // 1 2 [3, 4, 5]// 交换变量
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1
1.4 解构不成功与不完全解构
如果解构不成功,变量的值就等于 undefined
。
let [foo] = [];
let [bar, foo] = [1];
console.log(foo); // undefined
以上两种情况都属于解构不成功, foo
的值都会等于 undefined
。
另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。
let [a, b] = [1, 2, 3];
console.log(a,b); // 1,2let [a, [b], d] = [1, [2, 3], 4];
console.log(a,b,d); // 1,2,4
二、对象解构
2.1 基本用法
解构不仅可以用于数组,还可以用于对象。
// 传统方式
let obj = { name: 'John', age: 30 };
let name = obj.name;
let age = obj.age;// 解构赋值方式
let { name, age } = { name: 'John', age: 30 };
console.log(name, age); // John 30
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
console.log(foo, bar); // "aaa" "bbb"
如果解构失败,变量的值等于undefined
。
let {foo} = {bar: 'baz'};
console.log(foo); // undefined
上面代码中,等号右边的对象没有foo
属性,所以变量foo
取不到值,所以等于undefined
。
2.2 剩余模式与嵌套解构
剩余模式
let { a, b, ...rest } = { a: 1, b: 2, c: 3, d: 4 };
console.log(a, b, rest); // 1 2 {c: 3, d: 4}
与数组一样,解构也可以用于嵌套结构的对象。
let user = {name: 'John',address: {city: 'New York',country: 'USA'}
};let { name, address: { city, country } } = user;
console.log(name, city, country); // John New York USA
2.3 默认值
当然,对象解构也可以赋予默认值
let { name = 'Anonymous', age = 0 } = { name: 'John' };
console.log(name, age); // John 0let { a: x = 10, b: y = 20 } = { a: 5 };
console.log(x, y); // 5 20
三、混合解构
我们来看一个非常复杂的例子
const data = {users: [{ name: 'John', age: 30 },{ name: 'Jane', age: 25 },],total: 2,
}const {users: [{ name: firstName }, secondUser],total,
} = dataconsole.log(firstName,secondUser,total)
// John {name: 'Jane', age: 25} 2
其解释如下:
data
├── users: [
│ ├── { name: 'John', age: 30 } → firstUserName = 'John'
│ └── { name: 'Jane', age: 25 } → secondUser = 整个对象
│ ]
└── total: 2 → total = 2
四、函数参数解构
对象参数解构
// 传统方式
function greet(user) {console.log(`Hello, ${user.name}! You are ${user.age} years old.`);
}// 解构方式
function greet({ name, age }) {console.log(`Hello, ${name}! You are ${age} years old.`);
}greet({ name: 'John', age: 30 });
// Hello, John! You are 30 years old.
带默认值的参数解构
function createUser({ name = 'Anonymous', age = 0, isAdmin = false } = {}) {return { name, age, isAdmin };
}console.log(createUser());
// {name: 'Anonymous', age: 0, isAdmin: false}console.log(createUser({ name: 'John' }));
// {name: 'John', age: 0, isAdmin: false}
五、处理API响应数据
// 模拟API响应
let response = {status: 200,data: {users: ['John', 'Jane'],total: 2}
};let { status, data: { users, total } } = response;
console.log(status, users, total); // 200 ['John', 'Jane'] 2
六、注意事项
-
解构失败不会报错 - 未匹配的变量会得到
undefined
-
默认值只在值为
undefined
时生效 -null
被视为有效值 -
对象解构需要匹配属性名 - 顺序不重要
-
数组解构按顺序匹配 - 属性名不重要
-
不能使用已声明的变量 - 需要在解构时声明新变量