Object.assign({}, xyz)与Object.assign([], abc)是否存在差异?
关于
Object.assign({}, xyz)和Object.assign([], abc)的差异详解 嘿,这个问题问得特别到位!我刚接手旧项目的时候也碰到过这种“前后不一致”的写法,当时差点以为是前任开发者写错了,直到仔细啃了Object.assign的文档才明白其中的门道。核心差异其实都源于目标参数的类型不同,咱们一步步拆解:
先搞懂Object.assign的本质
Object.assign(target, ...sources)的核心逻辑是:把所有源对象的可枚举属性依次复制到目标对象上,最后返回修改后的目标对象。所以目标对象的类型,直接决定了最终返回值的类型,以及属性复制的行为逻辑。
两种写法的具体差异
1. Object.assign({}, xyz):目标是空对象
- 返回结果:永远是一个普通对象,哪怕
xyz是数组或者类数组对象。 - 复制逻辑:把
xyz的所有可枚举属性(包括数组的索引、length属性,甚至自定义属性)都作为键值对复制到新对象里。 - 示例:
const arr = [1, 2, 3]; arr.customProp = 'test'; // 给数组加个自定义属性 const objCopy = Object.assign({}, arr); console.log(objCopy); // {0: 1, 1: 2, 2: 3, length: 3, customProp: 'test'} console.log(Array.isArray(objCopy)); // false - 适用场景:
- 需要创建普通对象的浅拷贝,避免修改原对象;
- 把数组/类数组对象转成键值对形式的普通对象;
- 合并多个对象的属性到新对象中。
2. Object.assign([], abc):目标是空数组
- 返回结果:永远是一个数组,哪怕
abc是普通对象。 - 复制逻辑:
- 优先识别源对象中的数字类型索引(比如
0、1),把对应值填充到数组的对应位置; - 源对象的非数字属性(比如自定义属性)会被作为数组对象的额外属性保留(因为数组本质也是对象);
- 如果源对象有
length属性,会同步修改数组的length(但如果数字索引不连续,length会取最大索引+1和源length的较大值)。
- 优先识别源对象中的数字类型索引(比如
- 示例:
情况1:拷贝数组
情况2:处理普通对象const arr = [1, 2, 3]; const arrCopy = Object.assign([], arr); console.log(arrCopy); // [1, 2, 3] console.log(Array.isArray(arrCopy)); // true
情况3:处理类数组对象const obj = {name: 'Alice', age: 25}; const arrFromObj = Object.assign([], obj); console.log(arrFromObj); // [] (没有数字索引,数组内容为空) console.log(arrFromObj.name); // 'Alice' (数组对象保留了这个属性) console.log(arrFromObj.length); // 0const arrayLike = {0: 'a', 1: 'b', length: 2}; const realArr = Object.assign([], arrayLike); console.log(realArr); // ['a', 'b'] console.log(realArr.length); // 2 - 适用场景:
- 创建数组的浅拷贝;
- 把类数组对象(比如
arguments、DOM集合)转成真正的数组; - 合并多个数组的元素到新数组中(不过现在更常用
[...arr1, ...arr2])。
关键注意点
两种写法都是浅拷贝!如果源对象里有嵌套的对象或数组,拷贝后的对象/数组里的嵌套值仍然是原对象的引用,修改它们会影响原对象。比如:
const obj = { nested: { key: 'value' } }; const copy = Object.assign({}, obj); copy.nested.key = 'new value'; console.log(obj.nested.key); // 'new value' (原对象被修改了)
内容的提问来源于stack exchange,提问作者CodeMan03
相关产品推荐
相关产品推荐

