解构赋值有什么用?使用时有哪些注意点?
简化版
解构赋值可以从数组或对象中按结构取值,让代码更简洁。对象按属性名匹配,数组按位置匹配;可以设置默认值和别名,但默认值只在值为 undefined 时生效。
详细版
对象解构:
const user = { id: 1, name: 'Tom' };
const { id, name: userName } = user;
数组解构:
const [first, second] = [10, 20];
默认值:
const { page = 1 } = query;
注意默认值只对 undefined 生效:
const { a = 1 } = { a: null }; // a 是 null
函数参数解构常用于配置对象,但要给整体参数默认值,避免传入 undefined 报错。
完整版教学
一、对象解构按 key,数组解构按位置
对象没有顺序概念,解构看属性名;数组有顺序,解构看下标。
const { x, y } = point;
const [lng, lat] = coordinates;
这让代码表达更接近数据结构本身。
二、别名解决变量名冲突
对象属性名不一定适合当前变量名,可以起别名:
const { name: userName } = user;
这里真正声明的是 userName,不是 name。
三、嵌套解构要防空
const { profile: { avatar } } = user;
如果 profile 是 undefined,会报错。可以提供默认对象:
const { profile: { avatar } = {} } = user;
复杂数据中,过深解构反而降低可读性,要适度。
四、函数参数解构
function request({ url, method = 'GET' } = {}) {
// ...
}
最后的 = {} 很重要,它允许调用 request() 时不传参数。否则会对 undefined 解构而报错。
五、面试追问与工程落地
解构常见追问是“默认值什么时候生效”。只有解构结果严格等于 undefined 时默认值才生效,null、0、空字符串都不会触发默认值。这和 || 默认值不同,工程里要避免把合法的 0 或空字符串误替换掉。
还要注意函数参数解构的报错点。function f({ a }) {} 如果调用 f(),会对 undefined 解构导致报错。写公共函数时通常要给整体参数默认值:function f({ a } = {}) {}。
复杂接口数据不要过度嵌套解构。虽然一行能写出来,但一旦中间字段为空就容易崩,也不利于调试。更好的做法是先拿到关键对象,做空值判断,再解构局部字段。
六、按取值协议分析边界与副作用
对象解构按属性键读取,源值会先做对象转换,因此 null 和 undefined 不能直接被解构。数组解构更准确的说法是消费可迭代协议,而不是简单读取数字下标;这解释了为什么 Set 和字符串也能使用数组模式。默认值只在取到严格等于 undefined 时执行,null、0 和空字符串都不会触发。
const [a, b] = new Set([10, 20])
const { x = 1, y = 2 } = { x: null, y: undefined }
console.log(a, b) // 10 20
console.log(x, y) // null 2
| 输入值 | { value = 10 } 的结果 |
|---|---|
| 缺少属性 | 10 |
undefined | 10 |
null | null |
0 | 0 |
解构并非无副作用的“声明缩写”。读取 getter 会执行 getter,计算属性名会先求值,数组模式提前结束时还可能关闭迭代器;复杂表达式应避免为了少写几行而隐藏求值顺序。
面试中说“数组解构按位置”可以作为入门结论,但完整版回答应补一句“位置由迭代器产出的顺序决定”。
七、常见误区与追问
- 误区:默认值在属性为 null 时也会生效。 默认值只对
undefined生效,null通常表示调用方显式提供了空值。 - 误区:数组解构只能用于数组。 右侧只要实现可迭代协议即可,例如字符串、Set 和自定义迭代器。
- 误区:对象解构会复制整个对象。 它只是读取指定属性并绑定变量;读到对象值时仍共享同一引用。
- 追问:为什么 const { x } = null 会报错? 对象解构需要把源值转换为对象,
null和undefined无法完成这一步。 - 追问:如何同时改名并设置默认值? 使用
const { source: local = defaultValue } = obj,冒号左侧是属性键,右侧是本地变量。 - 追问:剩余属性会包含原型属性吗? 不会,它收集尚未取走的自有可枚举属性,不包含原型链成员。
- 追问:函数参数解构怎样避免漏参报错? 给整个参数对象设置默认值,例如
function f({ id } = {}) {},但仍要按业务验证必填字段。
八、加强记忆
解构赋值记住“对象按名,数组按位,默认只管 undefined”。它能让代码短,但不要为了炫技写过深解构,防空和可读性更重要。
看到解构题时依次确认取值协议、默认值触发条件和剩余属性范围,边界就不容易答错。