
文章目录
引言
在 JavaScript 中,Object.assign 和对象扩展运算符(...)是两种常用的对象合并和复制工具。它们都可以用于将一个或多个对象的属性复制到目标对象中,但它们在行为和使用场景上有一些关键区别。此外,它们都是浅拷贝,而不是深拷贝。本文将详细探讨 Object.assign 和对象扩展运算符的区别,并解释为什么它们是浅拷贝。
1. Object.assign 的基本用法
Object.assign 是 JavaScript 提供的一个静态方法,用于将一个或多个源对象的属性复制到目标对象中。
语法
Object.assign(target, ...sources)
target:目标对象,属性将被复制到该对象中。sources:一个或多个源对象,它们的属性将被复制到目标对象中。
示例
const target = { a: 1 };
const source = { b: 2, c: 3 };
const result = Object.assign(target, source);
console.log(result); // { a: 1, b: 2, c: 3 }
console.log(target); // { a: 1, b: 2, c: 3 }
特性
- 修改目标对象:
Object.assign会直接修改目标对象。 - 覆盖同名属性:如果目标对象和源对象有同名属性,源对象的属性值会覆盖目标对象的属性值。
- 浅拷贝:
Object.assign只会复制对象的可枚举属性,且是浅拷贝(即嵌套对象是引用复制)。
2. 对象扩展运算符的基本用法
对象扩展运算符(...)是 ES6 引入的语法,用于将一个对象的属性展开到另一个对象中。
语法
const result = { ...source1, ...source2 };
示例
const source1 = { a: 1, b: 2 };
const source2 = { b: 3, c: 4 };
const result = { ...source1, ...source2 };
console.log(result); // { a: 1, b: 3, c: 4 }
特性
- 不修改原对象:对象扩展运算符会创建一个新对象,不会修改原对象。
- 覆盖同名属性:如果多个源对象有同名属性,后面的属性值会覆盖前面的属性值。
- 浅拷贝:对象扩展运算符也是浅拷贝。
3. Object.assign 与对象扩展运算符的区别
| 特性 | Object.assign | 对象扩展运算符 (...) |
|---|---|---|
| 是否修改目标对象 | 是 | 否 |
| 返回值 | 返回目标对象 | 返回新对象 |
| 语法简洁性 | 较复杂 | 更简洁 |
| 适用场景 | 需要修改目标对象时 | 需要创建新对象时 |
| 性能 | 稍快(直接修改目标对象) | 稍慢(创建新对象) |
示例对比
// 使用 Object.assign
const target = { a: 1 };
const source = { b: 2 };
const result1 = Object.assign(target, source);
console.log(result1); // { a: 1, b: 2 }
console.log(target); // { a: 1, b: 2 }
// 使用对象扩展运算符
const source1 = { a: 1 };
const source2 = { b: 2 };
const result2 = { ...source1, ...source2 };
console.log(result2); // { a: 1, b: 2 }
console.log(source1); // { a: 1 } (未被修改)
4. 浅拷贝 vs 深拷贝
4.1 什么是浅拷贝?
浅拷贝是指只复制对象的第一层属性,如果属性值是对象(嵌套对象),则复制的是引用,而不是实际的对象。
示例
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = Object.assign({}, obj1); // 或使用 { ...obj1 }
obj2.b.c = 3;
console.log(obj1.b.c); // 3 (obj1 和 obj2 共享嵌套对象)
4.2 什么是深拷贝?
深拷贝是指递归复制对象的所有层级属性,包括嵌套对象,生成一个完全独立的新对象。
示例
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝
obj2.b.c = 3;
console.log(obj1.b.c); // 2 (obj1 和 obj2 完全独立)
4.3 为什么 Object.assign 和对象扩展运算符是浅拷贝?
- 它们只复制对象的第一层属性。
- 如果属性值是对象,则复制的是引用,而不是实际的对象。
5. 如何实现深拷贝?
5.1 使用 JSON.parse(JSON.stringify())
这种方法适用于简单的对象,但有以下限制:
- 无法复制函数、
undefined、Symbol等特殊值。 - 无法处理循环引用。
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = JSON.parse(JSON.stringify(obj1));
5.2 使用递归函数
手动实现深拷贝,适用于复杂对象。
function deepClone(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
const result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = deepClone(obj1);
5.3 使用第三方库
如 Lodash 的 _.cloneDeep 方法。
const _ = require("lodash");
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = _.cloneDeep(obj1);
6. 总结
Object.assign和对象扩展运算符都是浅拷贝工具,适用于合并或复制对象的属性。Object.assign会修改目标对象,而对象扩展运算符会创建一个新对象。- 如果需要深拷贝,可以使用
JSON.parse(JSON.stringify())、递归函数或第三方库(如 Lodash)。
参考资料
注意:在实际开发中,应根据需求选择合适的工具和方法,并注意浅拷贝和深拷贝的区别,以避免潜在的问题。

1195

被折叠的 条评论
为什么被折叠?



