Object.assign()创建深层副本还是浅层副本
Does Object.assign() create a deep copy or a shallow copy?
我刚刚发现的概念
var copy = Object.assign({}, originalObject);
其将原始对象的副本创建到";CCD_ 1";对象然而,我的问题是,这种克隆对象的方式是创建深度复制还是创建浅层复制?
PS:令人困惑的是,如果它创建了一个深度复制,那么它将是克隆对象的最简单方法。
如果要复制的对象的属性enumerable
属性设置为false,那么忘记深度复制,即使是浅层复制也是不安全的。
MDN:
Object.assign()方法仅复制可枚举属性和自己的属性从源对象到目标对象
以为例
var o = {};
Object.defineProperty(o,'x',{enumerable: false,value : 15});
var ob={};
Object.assign(ob,o);
console.log(o.x); // 15
console.log(ob.x); // undefined
使用Object.assign()
,实际上是在对对象执行浅层复制。每当我们做一个操作,比如将一个对象分配给另一个对象时,我们实际上会执行一个浅层复制,即如果OBJ1是一个对象,通过另一个OBJ2对象修改它也会反映OBJ1的变化。
对于小型Data structures
,我发现JSON.stringify()
和JSON.parse()
工作得很好。
// store as JSON
var copyOfWindowLocation = JSON.stringify(window.location)
console.log("JSON structure - copy:", copyOfWindowLocation)
// convert back to Javascript Object
copyOfWindowLocation = JSON.parse(copyOfWindowLocation)
console.log("Javascript structure - copy:", copyOfWindowLocation)
2023现在有了一种官方的JavaScript方法来深度克隆对象structuredClone()
但我建议您阅读文档并进行一些测试,因为某些克隆不起作用。https://developer.mozilla.org/en-US/docs/Web/API/structuredClone
例如,这会抛出一个错误:
var clone = structuredClone(window.location)
错误
VM673:1 Uncaught DOMException: Failed to execute 'structuredClone' on 'Window': Location object could not be cloned.
at <anonymous>:1:13
根据MDN:的这段话,它创建了一个浅拷贝
对于深度克隆,我们需要使用其他替代方案,因为Object.assign()复制属性值。如果源值是引用对象时,它只复制该引用值。
对于redux,Object.assign()
就足够了,因为redux应用程序的状态只包含不可变值(JSON)。
var copy = Object.assign({}, originalObject);
是否进行浅层复制,即更改副本也反映原始对象中的更改。因此,要执行深度复制,我建议使用lodash
克隆深度
import cloneDeep from 'lodash/cloneDeep';
var copy = cloneDeep(originalObject);
Object.assign仅创建浅拷贝。
const originalObject = {
api : 'POST',
contentType : 'JSON',
userData : {
name : 'Triver',
email : 'postaction@yahoo.com'
},
responseTime: '10ms'
}
const originalObjectRef = Object.assign({}, originalObject);
originalObjectRef.contentType = 'XHTML';
originalObjectRef.userData.name = 'Red John';
console.log(originalObject);
Output:
{
"api": "POST",
"contentType": "JSON",
"userData": {
"name": "Red John",
"email": "postaction@yahoo.com"
},
"responseTime": "10ms"
}
在浅拷贝中,引用变量主要存储它所引用的对象的地址。当一个新的引用变量被赋予旧引用变量的值时,存储在旧引用变量中的地址被复制到新引用变量中。这意味着新旧引用变量都指向内存中的同一对象。因此,如果对象的状态通过任何一个引用变量发生变化,则这两个变量都会反映出来。
注意:下面是ES6的浅层复制方式。
const originalObjectRef = {...originalObject};
希望这能帮助到别人,谢谢。
如上所述,copy
0将执行浅层克隆,无法复制源对象的自定义方法,并且无法使用enumerable: false
复制属性。
保留方法和不可枚举属性需要更多的代码,但不会花太多。
这将对数组或对象进行浅层克隆,复制源的方法和所有属性:
function shallowClone(src) {
let dest = (src instanceof Array) ? [] : {};
// duplicate prototypes of the source
Object.setPrototypeOf(dest, Object.getPrototypeOf(src));
Object.getOwnPropertyNames(src).forEach(name => {
const descriptor = Object.getOwnPropertyDescriptor(src, name);
Object.defineProperty(dest, name, descriptor);
});
return dest;
}
示例:
class Custom extends Object {
myCustom() {}
}
const source = new Custom();
source.foo = "this is foo";
Object.defineProperty(source, "nonEnum", {
value: "do not enumerate",
enumerable: false
});
Object.defineProperty(source, "nonWrite", {
value: "do not write",
writable: false
});
Object.defineProperty(source, "nonConfig", {
value: "do not config",
configurable: false
});
let clone = shallowClone(source);
console.log("source.nonEnum:",source.nonEnum);
// source.nonEnum: "do not enumerate"
console.log("clone.nonEnum:", clone.nonEnum);
// clone.nonEnum: – "do not enumerate"
console.log("typeof source.myCustom:", typeof source.myCustom);
// typeof source.myCustom: – "function"
console.log("typeof clone.myCustom:", typeof clone.myCustom);
// typeof clone.myCustom: – "function"
jsfiddle
- 处理一个JSON文件;完全相同的副本不是
- 如何使用object.assign()从其他对象引用基本对象属性
- 依次调用location.reload()和location.assign()
- 我如何制作一个文件的副本并用gump将其移动到父文件夹
- 如何在JS中创建对象的可变和不可变副本
- Object.assign(),函数方法和内存使用
- 是否可以使用Object.assign来克隆带有其方法的对象
- 保留未修改的dom节点副本问题
- 在不使用sort()的情况下获取HTML LI元素的副本
- 图像上传功能将++(+1)副本添加到下一次上传.出了什么问题或如何重置“选定图像”
- Issues with window.location.assign
- PDFObject:如何使用同一文件的不同副本重新加载容器
- 如何测试Greasemonkey脚本,尤其是在本地网页副本上
- 强制node.js使用OpenSSL的非发行版副本
- 何时需要使用Object.assign()方法来复制对象的实例
- lodash/underscore.js函数来创建由x的n个副本组成的数组
- 只能在第二次单击时将副本复制到剪贴板
- 将函数参数传递给Object.assign
- 从redis到elasticsearch的Node.js脚本副本内存不足
- Object.assign()创建深层副本还是浅层副本