JavaScript解构赋值仅支持可迭代对象和对象:数组、字符串、Map、Set等可数组解构;普通对象、Map键值对等可对象解构;undefined、null、数字、布尔值直接解构会报TypeError。
JavaScript 解构赋值只支持**可迭代(iterable)对象**和**对象(object)**,不是所有数据结构都能用。数组、字符串、Map、Set、arguments、NodeList 等实现了 [Symbol.iterator] 的,可以用于**数组解构**;普通对象、Map 的键值对(需配合 Object.entries())、模块导出等,适用于**对象解构**。
常见误区是以为 undefined、null、数字、布尔值能解构——它们不是对象也不是可迭代对象,直接解构会抛出 TypeError: Cannot destructure property 'x' of 'y' as it is undefined. 或类似错误。
Array、String、TypedArray:支持数组解构(const [a, b] = arr)Object:支持对象解构(const { x, y } = obj
)Map:需先转成数组(const [[k1, v1], [k2, v2]] = map)或用 for...of 配合解构Set:同数组解构(const [first, second] = new Set([1, 2]))undefined / null / Number / Boolean:直接解构报错,必须先做存在性判断或提供默认值解构时若目标对象不含对应属性,变量会得到 undefined,但不会报错——除非你试图对 undefined 做进一步解构(比如嵌套解构)。这时候得靠默认值或短路保护。
推荐写法是显式设默认值,而不是依赖后续判空:
const obj = { name: 'Alice' };
const { name, age = 25, tags = [] } = obj; // age 和 tags 有默认值
const { profile: { city = 'Unknown' } = {} } = obj; // 嵌套解构 + 默认空对象防崩
注意:profile: { city } 这种写法中,如果 obj.profile 是 undefined,就会报错;加个 = {} 就安全了。
undefined 时生效,null、false、0 都会原样赋值count = getDefaultCount()),且只在需要时执行{ userName: name = 'Anonymous' }
数组解构天然支持“跳过”和“收集”,靠逗号占位和扩展运算符 ... 实现,比手动索引清晰得多。
const arr = [1, 2, 3, 4, 5]; const [first, , third, ...rest] = arr; // first=1, third=3, rest=[4,5] const [, , , ...lastTwo] = arr; // lastTwo = [4,5] const [head, ...tail] = arr; // head=1, tail=[2,3,4,5]
常见陷阱是误以为 ... 可以放在任意位置——它只能是最后一个元素,否则语法报错:const [...mid, last] = arr ❌ 不合法。
[a, , , d] 表示取第 0 和第 3 个元素undefined
arguments)也能解构,前提是它有数字键和 length
函数参数支持直接解构,写起来简洁,但默认值逻辑和调用时传参方式容易混淆。特别是当参数本身是 undefined 时,解构默认值才生效;而传了 null 或空对象,就可能意外触发深层解构错误。
function connect({ host = 'localhost', port = 3000, timeout = 5000 } = {}) {
// 注意这里的 = {}:给整个参数对象设默认值,防传 undefined
console.log(host, port, timeout);
}
connect(); // ✅ 正常:localhost 3000 5000
connect({}); // ✅ 正常:同上
connect({ host: 'api.example.com' }); // ✅ host 覆盖,其余用默认
connect(null); // ❌ 报错:Cannot destructure property 'host' of 'null'
所以函数参数解构前加 = {}(或 = [])几乎是必须的,除非你明确要求调用方必须传对象。
function f([a, ...rest], ...others) 是合法的,但 function f(...[a, b]) ❌ 语法错误const fn = ({ id, name }) => console.log(id)
= {} 或 = [] 往往比后续一堆 ?. 或 || 更清晰。