来自C ++背景,以及JS的新手,我想做一个对象的深层复制。
这是我想用OOP语言做的事情(仍在学习JS语言)。
我将foo类的虚拟对象传递给doSomething类的构造函数。
每当doSomething需要对foo做一些事情时,它会深度复制虚拟foo对象,自定义它并将新副本存储到数组中。
foo对象数组中应该有不同的foo对象。但是,存储在数组中的所有对象都“引用”处理的最后一个foo对象。
在我看来,它存储了对虚拟对象的引用。
我尝试了帖子中提出的方法 What is the most efficient way to deep clone an object in JavaScript? ,但没有得到我想要的。我在下面的代码示例中使用_.cloneDeep()作为示例。
========================= code ===================== ==
我有一个foo.js
define(["jquery", "react", "react-dom", "react-components"],
function($, React, ReactDOM, ReactComponents) {
"use strict";
function foo(x, y, z) {
var $x = x,
$y = y,
$z = z;
function f1 () {}
function f2 () {}
function setX(x) {}
function setY(y) {}
function whichFoo() {//prints to the console to identify which object it is}
return {
f1: f1,
f2: f2,
setX: setX,
setY: setY,
whichFoo: whichFoo
};
}
return foo;
});
我有一个创建foo的index.html并将其传递给doSomething.js:
<script>
require(['doSomething', 'foo'], function(doSomething, foo) {
var aFoo = foo(null, null, null);
doSomething(aFoo);
}
</script>
这是doSomething.js:
define([various libraries], function(various libraries) {
"use strict";
function doSomething(aFoo) {
var dummyFoo = _.cloneDeep(aFoo), // I understand aFoo is a reference so deepcopy it here to create a different object.
fooList = [];
// other functions;
function run() {
// an object of ids is created here.
_.each(ids, callback);
}
function callback(k, v) {
var newX = getX(v),
newY = getY(v);
var newFoo = _.cloneDeep(dummyFoo); // creates a copy of object for customization
// customize newFoo
newFoo.setX(newX);
newFoo.setY(newY);
newFoo.whichFoo(); //verified different foo each time.
fooList.push(newFoo);
}
function loopFooList() {
for (var i = 0; i < fooList.length; i++) {
fooList[i].whichFoo(); // every item in the list references the foo created in the last callback...
}
}
return {...};
}
return doSomething;
}
根据我的理解,_.cloneDeep()在不同的内存位置创建一个克隆的对象的新对象,并返回对新对象的引用。所以即使fooList存储引用(不是实际对象),它们也应该引用它们各自的对象,为什么最终它们引用最后创建的对象?
我觉得JS意义上的深度复制不同于C ++。任何人都可以告诉我为什么我的代码没有按照预期的方式工作,并指出JS在实现我想要的方式(深度复制C ++意义上的对象)?
PS:我之所以使用这种奇怪的自定义虚拟对象的方法,而不是每次需要时都在doSomething中创建foo的新实例,是因为我需要避免使用doSomething加载反应组件,这会导致测试中超时(但它没有加载index.html进行测试),我无法改变。所以这是一个黑客:)但它不会影响深层复制的结果。