ES6扩展运算符无法合并带键对象?求正确实现方法
为什么ES6扩展运算符没合并对象反而出问题?正确做法看这里!
哈哈,这个坑我刚接触ES6对象扩展的时候也踩过!先给你拆解下问题出在哪,再给你正确的实现方式。
问题根源:用错了扩展运算符的场景
你写的console.log(...a, b)存在两个核心问题:
- 普通对象不能直接用扩展运算符展开到函数参数里:数组、字符串这些有内置迭代器的类型可以用
...展开到参数列表,但普通对象默认没有迭代器,直接这么写会抛出TypeError: Found non-callable @@iterator的错误,根本跑不起来。 - 合并对象的扩展运算符用法不对:对象扩展运算符
...的作用是把一个对象的可枚举属性复制到新的对象字面量中,而不是在函数参数里用来合并。你想合并对象,得把...a和...b放在一个新的对象字面量里才行。
正确的实现方法
1. ES6扩展运算符(浅合并,最常用)
这是ES6推荐的简洁写法,能把多个对象的属性合并到一个新对象里:
let a = { key1: { floo: 'blar' } } let b = { key2: { floo: 'blar' } } // 把a和b的属性都复制到新对象中 let mergedObj = { ...a, ...b } console.log(mergedObj); // 输出:{ key1: { floo: 'blar' }, key2: { floo: 'blar' } }
注意:这是浅合并——如果a和b有同名的嵌套对象,后面的会直接覆盖前面的,而不是合并内部属性。比如如果a = { key1: { foo: 'bar' } },b = { key1: { baz: 'qux' } },合并后key1会变成{ baz: 'qux' },原来的foo会丢失。
2. Object.assign()(ES6另一种浅合并方式)
和扩展运算符效果完全一致,也是浅合并:
let mergedObj = Object.assign({}, a, b); console.log(mergedObj);
这里第一个参数{}是目标对象,用空对象是为了不修改原有的a和b;如果直接写Object.assign(a, b),会把b的属性合并到a里,直接修改原对象a。
3. 深度合并(如果需要嵌套对象也合并)
如果你的对象有多层嵌套,需要合并内部属性而不是覆盖,那ES6原生方法做不到,得自己写一个深度合并函数,比如:
function deepMerge(target, ...sources) { if (!sources.length) return target; const source = sources.shift(); if (isObject(target) && isObject(source)) { for (const key in source) { if (isObject(source[key])) { if (!target[key]) Object.assign(target, { [key]: {} }); deepMerge(target[key], source[key]); } else { Object.assign(target, { [key]: source[key] }); } } } return deepMerge(target, ...sources); } function isObject(item) { return item && typeof item === 'object' && !Array.isArray(item); } // 使用示例 let a = { key1: { floo: 'blar', test: 'hello' } } let b = { key1: { floo: 'new value' }, key2: { foo: 'bar' } } let mergedObj = deepMerge({}, a, b); console.log(mergedObj); // 输出:{ key1: { floo: 'new value', test: 'hello' }, key2: { foo: 'bar' } }
内容的提问来源于stack exchange,提问作者yak
相关产品推荐
相关产品推荐

