JavaScript cloning a “class” instance
我有一门课是这样的:
1 2 3
| function Element(){
this.changes = {};
} |
现在我有一个这样的"类"实例,el = new Element()。这些实例存储在一个数组中,如elements.push(el)。
这个元素数组现在存储在一个对象中,然后将该对象推入一个数组(states)。
现在有些情况下,我需要一个元素的副本,所以我需要做一些类似于var cloned = $.extend(true, {}, states[0])的事情。在这里,我假设我们正在克隆第一个状态。
现在的问题是,我所得到的,state[1].elements[0]仍然指向原始实例。因此,我对克隆对象所做的任何更改也会更改原始对象。
被困在这样一个小问题上真令人沮丧…
我创造了一把小提琴来测试它:http://jsfiddle.net/e6wlw/
- 我似乎无法复制它,请看一下这个jsiddle。
- 查看:stackoverflow.com/questions/728360/…
- 我刚添加了一个指向JSfiddle代码段的链接
- 另外,我对这个问题做了更多的修改
- 您要做的是一个"深度复制"操作。根据对象内容和性能需求,一个可能有效的非常简单的事情是JSON对对象进行编码,然后再次对其进行解码。
- 正确的解决方案是重新设计算法以消除深度复制的需要。深度复制是一个噩梦:a)做对了;b)计算代价很高;c)创建依赖于深度复制所有内容的逻辑。深拷贝是一个很难解决的问题,应该通过使用浅拷贝来简单地避免。
$.extend只是克隆普通对象。如果对象有一个构造函数,那么它不是克隆的,而是复制的。
从$.extend来源:
1 2 3 4 5 6
| if ( jQuery.isPlainObject(copy) /* ... */) {
// do the recursive $.extend call and clone the object
} else if ( copy !== undefined ) {
target[ name ] = copy;
// ^^^^^ just copy
} |
因此,$.extend()将调用isPlainObject(el),返回false,因为el有一个构造函数,而不是复制el。因此,states[1].elements[0]与states[0].elements[0]是同一对象,因为它不是克隆的。
如果我们修改您的示例:
1 2 3 4 5
| function Element(){
this.changes = {};
}
var el = new Element(); // $.isPlainObject(el); <- false
// ... |
进入:
1 2
| var el = { changes: {} }; // $.isPlainObject(el); <- true
// ... |
它将正确克隆el。看这儿。
- 所以基本上jquery的扩展方法是愚蠢的。
- @Raynos $.extend()无法使用构造函数完全支持对象,因为它不知道要使用什么参数。
- 使用什么参数无关紧要。他们所需要做的就是将对象属性逐个复制。这很容易做到。
- @Raynos,这不是您所需要做的全部工作,因为您拥有对象的所有属性,但是原型不正确,它远不是一个"克隆"。或者我错过了什么:)?
- @raynos stackoverflow.com/a/728694/1011582包含一些有关尝试克隆非平面对象时出现问题的信息。
- 克隆。忽略了大量的边缘情况和你必须要做的黑色魔术,克隆函数的核心非常简单。主要的问题领域是主机对象和具有内部魔力的本机对象。以及避免在深度复制中循环引用。
- @Raynos看起来不错,但我不认为$.extend()应该实现类似的功能,除非它可以做所有的黑魔法来完全支持它)。
您可以使用http://documentcloud.github.com/underline/克隆来克隆对象,例如:
1
| var cloned = _.clone(states[0]); |
- 这行不通。阅读你发布的链接:Any nested objects or arrays will be copied by reference, not duplicated.。