Cloning a JavaScript object?
Possible Duplicate:
How to clone js object?
这是创建JavaScript对象的另一种方法(使用对象文字符号而不是函数):
有克隆这个对象的方法吗?还是它是单例的?
- Javascript object!=JSON Object.你提供的例子是一个文学杂志,我根据需要更新你的邮件。
- 问得好我会一直认为用户会复制,但不要。
- 短答案:是和是。Distr.
- 你选择的答案仍然不是一个深拷贝我的答案仍然是最好的。
- 你选择的答案不会产生不同的结果。功能仅因制造商名称的改变而改变。不是克隆,而是复制参考!!
- @Omshankar,这是不准确的。见我的答案后面的Marzsocks。
- @Dagnabbit,你的代码有疑问,不实现它的目的。在你指点的人下面查看我的评论。The created object has a reference to the same object.所以这不是克隆如果我们想做你的方法是做什么的话,我们就不需要在JS中有克隆,因为在JS中没有任何作弊的可能性。
- @Dagnabbit,also,this is Javascript.所以你有链接说明克隆不是一个浅拷贝还是一个深拷贝,这就是人们的观点。作为一个人类的定义,它可能是Javascript物体或现实世界,只有在创作时保留原始特性。他们不需要每一个国家或财产的改变都跟随另一个国家。
- @Omshankar,请停止试着用你的方式离开一个洞。代码清晰地实现了它的目的,就像它帮助了询问者一样。如果用"没有任何作弊"来代替Object.create,请在这些邮件上注明日期。你其余的评论是完全不敏感的,除非你拿走"深拷贝"才是"克隆"的唯一可接受的定义,这是荒谬的。
- @Dagnabbit,为什么在你的方法中原始物体改变的性质?这是针对克隆的也许这就是我可以问你的智慧问题的简单方式,在很多评论之后,你的智慧是不可能理解的怀疑的。
- @Omshankar,like it or not,this is an accepted definition of cloning in prototypal languages(arguably the most common common),and that's just the way it works.而且课程改变了原始物体的属性不改变克隆本身的属性。如果我们要问其他人的智慧,我会问你的原始说法,即这与var user2 = user;一样,因为这不是课程,新的对象可以拥有原始的影子。对不起,你不喜欢克隆的定义
- 改变原始物体的特性改变了克隆的特性。这就是人们对这里的评论编辑:Acc to you,John Resig also understands cloning in a wrong way,then.注:
- 这并不是改变克隆本身的特性。这就是我为何要自己紧张。Own,as in hasOwnProperty在cloneNode之后,JQuery's clone是一个明确的名称,它是一个DOM函数,并与Javascript或原型语言中的"克隆"的常见定义(DOM Stuff is Language-Agnostic)。
试试这个:
1 2 3 4
| var clone = (function(){
return function (obj) { Clone.prototype=obj; return new Clone() };
function Clone(){}
}()); |
这是发生的事情。
- 克隆是一个虚拟构造函数。
- 我们将要克隆的对象分配给克隆构造函数的原型。
- 我们使用"new"来调用克隆,因此构造的对象将原始对象作为其构造函数的原型aka(非标准)__proto__。
克隆的对象将共享原始对象的所有属性,而不复制任何内容。如果克隆对象的属性被分配了新值,它们将不会干扰原始对象。而且不需要篡改内置组件。
请记住,新创建对象的对象属性将引用与克隆对象同名的属性相同的对象。将新值赋给克隆的属性不会干扰原始值,但将值赋给克隆的对象属性会。
在Chrome或Firebug控制台中尝试此操作:
1 2 3 4 5 6 7 8
| var user = {
name :"Foo",
email :"[email protected]"
}
var clonedUser = clone (user );
console. dir(clonedUser ); |
这里可以找到这种克隆技术的详细解释。
- user={name:"",email:"",obj:{a:"A"}}; clonedUser=clone(user);和clonedUser.obj.a="B";你会发现user.obj.a =="B"。
- 这看起来也和克里斯J的答案非常相似。
- vol7ron:是的,因为user.obj和clonedurer.obj引用同一个对象。将新值赋给newuser的obj属性将不会显示这种行为。请求是一个克隆,不是一个副本,也不是一个深度副本。请看我答案末尾的链接。
- @不:很好,如果你编辑答案,我将取消我的否决权:)这是正确的,但是在文章中对编程的clone的定义和对克隆的本地定义有很大区别。
- 不过,文章定义A克隆是B。A对财产进行了更改,B看到了。B对财产作了变更,A没有给出-。在您的示例中,它们都共享一个嵌套对象。如果B对该对象的属性进行更改,A不应看到更改。总之,不鼓励克隆,鼓励深度复制。
- 不,克隆B在克隆完成后不会看到对原始对象A属性的更改…自己试试看。当然,除非您的意思是更改克隆和原始对象共享的对象属性。
- 后者,其中已存在嵌套对象的属性。该属性的更改将在超类中看到。即使向该内部对象添加属性,也可以在两者中看到。
- 是的,这是像这样的浅操作所需要的行为。如果需要,可以很容易地创建深度克隆功能。同样,这个问题问的是克隆,而不是副本、深度副本或深度克隆。
- 我真的很好奇Ajsie到底想要什么,我的猜测是一个深刻的副本。
- @伏尔7龙。我在我的帖子里不清楚我的意思,不知道有肤浅和深刻的复制/克隆。复制和克隆是一回事吗?然而,我正在寻找一种复制相同副本的方法,也就是说,我猜是深度复制,还是深度克隆=)这个答案仍然有效?
- 不,我怀疑你会想要一份完整的副本;你会想要我的解决方案,尽管火焰大战的否决
- 这与执行以下操作相同:var obj2=obj1;存在一个传递引用,它不是对象的真正新实例。
- @Marzsocks,不,不是。试试看,obj2 === obj1将返回false。它使用原型链中的旧对象创建新对象,而不是对现有对象的引用。
- @达格纳比,绝对错误!!创建一个对象:var abc = {a: 1, b: 2},然后尝试使用您的方法执行var def = clone(abc);。注意到改变abc.a也改变了def.a,lol.克隆是怎样的??只有当它们指向同一参考时,才会发生这种情况。
- @达格纳比,还有,你的代码是可疑的。与IIF中一样,function Clone(){}被吊起来,所以把它放在return声明之后是令人困惑的。
- @暗善卡尔,我已经在我的回答中说明了你的观点。函数提升是JavaScript的一部分,不含糊。我不知道这为什么会让你困惑。
- @达格纳比,是的,它是一个部分。但是将函数定义放在主逻辑之后是令人困惑的。混淆并不一定意味着不可理解。某些可以理解的东西,目的上也可能是混淆的。
- 好的,那么。
您可以使用json对象(在现代浏览器中存在):
1 2 3 4 5
| var user = {name :"Foo", email :"[email protected]" }
var user2 = JSON. parse(JSON. stringify(user ))
user2. name ="Bar";
alert (user. name +"" + user2. name); // Foo Bar |
请参见jsFiddle中的。
编辑
如果在旧的浏览器中需要,请参阅http://www.json.org/js.html。
- 隐马尔可夫模型。。。不会投你反对票,但在我看来,这是愚蠢的。首先,如果要使用JSON,则需要在页面中包含JSON2.js,因为当前仍有没有本机JSON的浏览器,并且这些浏览器将在一段时间内经常使用非本机JSON。要么编写或借用扩展实现,要么包含一个具有扩展实现的库。
- 我只是在给你另一种方法。如果一个站点已经有json2.js,那么它可以工作。
- 如果一个对象同时具有properties和methods,那么我的朋友,使用这种JSON样式,methods不会被克隆。
- 其实没那么傻…例如,如果您正在为嵌入式系统创建一个应用程序,那么您总是知道它将运行在什么浏览器上;并且您知道它是一个数据对象(所以您不关心方法是否被克隆),那么这是简单、干净和安全的。它不适用于所有应用程序,但它非常适合我想要的应用程序!谢谢!
我喜欢用这个:
1 2 3 4 5 6 7
| if (typeof Object.create !== 'function') {
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
} |
然后,我要克隆的任何对象都可以执行以下操作:
如(或类似)javascript所示,好的部分
- 你不应该这样做,看康克斯的回答。
- @马塞尔感谢你指出这一点。我会保留我的答案,并推荐康克斯的解释作为一个好的读物。
- @Marcel/Chris+1;Kangax的回答是,Create并没有把两个属性带到任何地方。我的感觉是如果每个人都使用这种方法,那么它将迫使供应商遵守标准。最初我没有使用FF,因为它没有正确地显示所有内容,现在网络变得更智能了,FF做了一些修改,以便在QuirksMode中更好地工作。如果程序员局限于标准并推动接受标准的浏览器,情况也是如此。
- 如果javascript能够提供一种简单的克隆对象的方法,那就太好了。
- 我最喜欢那个。
大多数JavaScript框架都支持对象克隆。
1 2
| var a= {'key':'value'};
var b= jQuery.extend( true, {}, a ); |
- 同意:underlinejs还有一个clone方法underlinejs.org/clone
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| Object. prototype. clone = function clone (obj ) {
obj = obj || this;
var new_obj = {};
for( var p in obj ) {
if ( obj. hasOwnProperty(p ) ) {
if( obj [p ] !== null && typeof(obj [p ]) ==="object" ) {
new_obj [p ] = clone ( obj [p ] );
}
else {
new_obj [p ] = obj [p ];
}
}
}
return new_obj ;
};
/* Example */
var foo = {
name : "Foo"
, email :"[email protected]"
, obj : {a :"A",b :"B"}
};
var bar = foo. clone();
bar. name ="Bar";
bar. obj. b ="C";
// foo and bar should have a different 'name'
// foo and bar should retain the same email
// foo and bar should have different values for <foo/bar>['obj']['b']
// foo and bar should have the same values for <foo/bar>['obj']['a']
console. dir(foo );
console. dir(bar ); |
- 不不不…不要乱弄object.prototype,你会破坏一切的:p
- 这是不正确的,除非你是使用JQuery的无人机之一,否则永远不要搞砸任何事情,忘了怎么做。
- 别生气。我通常避免jquery。不过,有两件事……1,这不是克隆,而是复制品。"克隆"这个名字与这种技术有关:oranlooney.com/functional-javascript
- 2、不要乱用对象和数组之类的内置组件,不是因为jquery,而是因为当使用in迭代对象时,有人会忘记使用hasownproperty,突然间他们会有额外的属性,因为另一个开发人员在不知道的情况下修改了内置组件。
- @不:你要记住一点,但我认为这还不够好,根本不足以说"不要搞砸原型"。
- @不:不,又错了。你在击球0
- 所有的否定,但这仍然是最好的答案。
- 当克隆null时,您的代码会给出错误的结果,因为typeof(null) ==="object!用if(a !== null && typeof(a)==="object")代替…(如果我没记错的话,它也会闯入.
- @Alexander255我认为你是对的,可能有很多事情可以做来改进这一点;特别是自从这个答案被提交以来已经5年了:)当我有时间的时候,我会尝试更新,如果没有,我希望有人能读到通信。
- 我年轻的自己听起来像个混蛋,但问题的简单事实是,在核心对象上使用prototype来提供其他浏览器中存在的功能,或提供浏览器(或ecma语言)本应存在的功能,例如深度复制或克隆方法,从而存在多填充和填隙。现在,我更喜欢使用Object.keys(obj)来获取对象的非原型密钥,而不是in。这是个人的偏好,但对于下一个必须维护我的工作的人来说,更容易遵循代码。