如何正确克隆 JavaScript 对象?

I have an object, x. I'd like to copy it as object y, such that changes to y do not modify x. I realized that copying objects derived from built-in JavaScript objects will result in extra, unwanted properties. This isn't a problem, since I'm copying one of my own, literal-constructed objects.

How do I correctly clone a JavaScript object?

转载于:https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object

weixin_41568126
乱世@小熊 If you are suggesting Object.create() then you know very little about JS. Object.create will not clone the object X. Y = Object.create(X) does this and nothing more: Creates a new object Y with X as its prototype. The object X will become the prototype of Object Y. That is not what you want. At all. Because X's methods and data are not copied to Y, they are referenced, Y holds a reference to X's data and methods. How wrong can you be!?
3 年多之前 回复
csdnceshi69
YaoRaoLov {...original}
3 年多之前 回复
csdnceshi50
三生石@ Seems like I can call JSON.parse and JSON.stringify after all inside QC. Core functions after all. Also i did find this polyfill on the reference page and links to more advanced polyfills JSON2 and JSON3: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
3 年多之前 回复
csdnceshi78
程序go developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - just tried this on the chrome developer terminal - oj1={}; oj1.p1=222; oj2={}; Object.assign(oj2,oj1); oj2.p1=555; oj1.p1; - this will show 222 Also answered here : stackoverflow.com/a/36177142/482176
3 年多之前 回复
csdnceshi50
三生石@ what if you're in a javascripting environment where you can't import libraries like JSON. Apple's Quartz Composer Editor for example, not sure about Adobe CC scripting.
3 年多之前 回复
csdnceshi55
~Onlooker That does not copy the object. It creates a new variable and makes it point to the same object.
接近 4 年之前 回复
csdnceshi73
喵-见缝插针 why OP cannot store object into new variable ? like var copyobject=object ??
接近 4 年之前 回复
csdnceshi75
衫裤跑路 here a benchmark of different solutions: jsben.ch/#/bWfk9
接近 4 年之前 回复
csdnceshi63
elliott.david that will not work... Please post only after doing basic test of the solution..
4 年多之前 回复
weixin_41568183
零零乙 how about var newObj = (function(){ return oldObj; }());
4 年多之前 回复
weixin_41568131
10.24 Object.create does not get you __proto__, it gets you a new object, with it's prototype pointing to the argument, thus creating a chain. I agree that it is maybe not a real 'clone' in the traditional sense, but depending on the situation Object.create is much more consistent than using various cloning techniques used below. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
大约 5 年之前 回复
csdnceshi76
斗士狗 - because it doesn't work even for flat objects? (Chrome 45). You just get __proto__, not a clone...
大约 5 年之前 回复
csdnceshi70
笑故挽风 var x = { deep: { key: 1 } }; var y = Object.create(x); x.deep.key = 2; After doing this, y.deep.key will also be 2, hence Object.create CAN NOT BE USED for cloning...
大约 5 年之前 回复
weixin_41568196
撒拉嘿哟木头 Object.create works great if you want to copy your object's prototype.
大约 5 年之前 回复
csdnceshi80
胖鸭 Fair enough, although I could argue that OP wanted an "elegant" [sic] way and not everyone would necessarily agree that using a polyfill fits that description. I was just trying to provide you with a possible reason why Object.create hasn't been suggested (if that's the case), which is why I wrote "Probably". Regardless, I'm in favor of polyfills and recently looked at this one incidentally, which is similar to your snippet. If you're after better feedback you could also consider adding your suggestion as an answer.
大约 6 年之前 回复
weixin_41568131
10.24 That's not a good argument at all. There are lots of polyfills for Object.create that can be found, as for instance: refheap.com/90006
大约 6 年之前 回复
csdnceshi80
胖鸭 Probably because it's not supported in IE8 and under.
大约 6 年之前 回复
weixin_41568131
10.24 I really don't get why no one suggests Object.create(o), it does everything the author asks?
大约 6 年之前 回复
csdnceshi78
程序go For JSON, I use mObj=JSON.parse(JSON.stringify(jsonObject));
7 年多之前 回复
csdnceshi65
larry*wei Definitely support @Niyaz! Shortlink: tinyurl.com/JSCopyObject
接近 9 年之前 回复
weixin_41568184
叼花硬汉 See this question: stackoverflow.com/questions/122102/…
9 年多之前 回复

22个回答

To do this for any object in JavaScript will not be simple or straightforward. You will run into the problem of erroneously picking up attributes from the object's prototype that should be left in the prototype and not copied to the new instance. If, for instance, you are adding a clone method to Object.prototype, as some answers depict, you will need to explicitly skip that attribute. But what if there are other additional methods added to Object.prototype, or other intermediate prototypes, that you don't know about? In that case, you will copy attributes you shouldn't, so you need to detect unforeseen, non-local attributes with the hasOwnProperty method.

In addition to non-enumerable attributes, you'll encounter a tougher problem when you try to copy objects that have hidden properties. For example, prototype is a hidden property of a function. Also, an object's prototype is referenced with the attribute __proto__, which is also hidden, and will not be copied by a for/in loop iterating over the source object's attributes. I think __proto__ might be specific to Firefox's JavaScript interpreter and it may be something different in other browsers, but you get the picture. Not everything is enumerable. You can copy a hidden attribute if you know its name, but I don't know of any way to discover it automatically.

Yet another snag in the quest for an elegant solution is the problem of setting up the prototype inheritance correctly. If your source object's prototype is Object, then simply creating a new general object with {} will work, but if the source's prototype is some descendant of Object, then you are going to be missing the additional members from that prototype which you skipped using the hasOwnProperty filter, or which were in the prototype, but weren't enumerable in the first place. One solution might be to call the source object's constructor property to get the initial copy object and then copy over the attributes, but then you still will not get non-enumerable attributes. For example, a Date object stores its data as a hidden member:

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

var d1 = new Date();

/* Executes function after 5 seconds. */
setTimeout(function(){
    var d2 = clone(d1);
    alert("d1 = " + d1.toString() + "\nd2 = " + d2.toString());
}, 5000);

The date string for d1 will be 5 seconds behind that of d2. A way to make one Date the same as another is by calling the setTime method, but that is specific to the Date class. I don't think there is a bullet-proof general solution to this problem, though I would be happy to be wrong!

When I had to implement general deep copying I ended up compromising by assuming that I would only need to copy a plain Object, Array, Date, String, Number, or Boolean. The last 3 types are immutable, so I could perform a shallow copy and not worry about it changing. I further assumed that any elements contained in Object or Array would also be one of the 6 simple types in that list. This can be accomplished with code like the following:

function clone(obj) {
    var copy;

    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = clone(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}

The above function will work adequately for the 6 simple types I mentioned, as long as the data in the objects and arrays form a tree structure. That is, there isn't more than one reference to the same data in the object. For example:

// This would be cloneable:
var tree = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "right" : null,
    "data"  : 8
};

// This would kind-of work, but you would get 2 copies of the 
// inner node instead of 2 references to the same copy
var directedAcylicGraph = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "data"  : 8
};
directedAcyclicGraph["right"] = directedAcyclicGraph["left"];

// Cloning this would cause a stack overflow due to infinite recursion:
var cyclicGraph = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "data"  : 8
};
cyclicGraph["right"] = cyclicGraph;

It will not be able to handle any JavaScript object, but it may be sufficient for many purposes as long as you don't assume that it will just work for anything you throw at it.

csdnceshi61
derek5. Object assign doesn't seem to make a true copy in Chrome, maintains reference to original object - ended up using JSON.stringify and JSON.parse to clone - worked perfectly
接近 3 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 as improvement, instanceof is 30% slower than typeof a==="object".
大约 3 年之前 回复
csdnceshi52
妄徒之命 I wonder if this answer isn't already obsolete with javascript's new features as Object.assign. Would Tareq's answer be a better one?
3 年多之前 回复
csdnceshi57
perhaps? Why can't just use Object.assign({},{name: 'ankit'},{age: 23}, someOtherObject);
3 年多之前 回复
csdnceshi64
游.程 Nothing much... Just mentioning that real-world implementation might benefit if the if (obj instanceof Array) check and code are placed before the if (obj instanceof Date) check and code, since this might be more often used to clone Arrays than Dates. Useful especially in multidimensional arrays.
大约 4 年之前 回复
weixin_41568127
?yb? I would include array into the object type copy = obj instanceof Array ? []:Object.create(obj.constructor.prototype); , other way it would fails cloning the following object: var obj = []; obj[5] = true;
4 年多之前 回复
weixin_41568126
乱世@小熊 Good suggestion. Although, if you look at my explanation, I had assumed that you would only copy objects which are one of the 6 basic types that I mentioned. But copying the prototype would make it work in more situations.
大约 5 年之前 回复
weixin_41568174
from.. Wouldn't you want the new object to have the same prototype? copy.prototype = obj.prototype;
大约 5 年之前 回复
weixin_41568208
北城已荒凉 One issue with this clone is when you have array of objects which modifying it in the following way fixed it for me (in place of array case: if (obj instanceof Array) { copy=[]; for (i=0;i<obj.length;i++) { copy[i]= clone(obj[i],level-1); } return copy; } I also added a level variable in clone function that I can limit the deepnes to overcome overflow on big objects
5 年多之前 回复
csdnceshi60
℡Wang Yan (null == undefined) === true;
接近 6 年之前 回复
csdnceshi80
胖鸭 for those, who wants to clone complex objects; changing copy[attr] = obj[attr]; to copy[attr] = clone(obj[attr]); will work.
接近 6 年之前 回复
csdnceshi53
Lotus@ You'd better check if array element exists before copying it: if (i in obj) .... Since it might not.
接近 6 年之前 回复
csdnceshi73
喵-见缝插针 To copy a Date, use: return new Date(+obj). instanceOf fails across global contexts (e.g. frames), better to use Object.prototype.toString.call(obj) == '[object Date]';.
接近 6 年之前 回复
csdnceshi59
ℙℕℤℝ In the first snippet, are you sure it shouldn't be var cpy = new obj.constructor()?
接近 6 年之前 回复
csdnceshi54
hurriedly% Line 5 in the first snippet should be: if (null == obj || "undefined" == typeof obj) return obj;
接近 6 年之前 回复
csdnceshi58
Didn"t forge would this implementation do the job?
接近 6 年之前 回复
weixin_41568131
10.24 getOwnPropertyNames
接近 6 年之前 回复
csdnceshi65
larry*wei Missing opening bracket in the "Wait for 5 seconds" while loop.
大约 7 年之前 回复
csdnceshi56
lrony* JSON.stringify() fails to convert circular structures: "TypeError: Converting circular structure to JSON."
接近 8 年之前 回复
weixin_41568184
叼花硬汉 Since typeof will return "function" for a method, it should work. Unless your methods are non-trivial closures, in which case… I don't really think there's anything (generic) you can do; whatever code generated the methods, you'll need similar code to copy them.
大约 8 年之前 回复
csdnceshi77
狐狸.fox How about also copying methods of objects. Is that possible?
大约 8 年之前 回复
csdnceshi71
Memor.の Would nowadays JSON.parse(JSON.stringify([some object]),[some revirer function]) be a solution?
8 年多之前 回复
weixin_41568134
MAO-EYE For future googlers: same deep copy, passing references recursively instead of using 'return' statements at gist.github.com/2234277
8 年多之前 回复
weixin_41568134
MAO-EYE almost worked fine in a nodejs - just had to change the line for (var i = 0, var len = obj.length; i < len; ++i) { to for (var i = 0; i < obj.length; ++i) {
8 年多之前 回复
csdnceshi67
bug^君 here is a tweak to your excellent answer. If you know the prototype chain you need, you can supply it in an optional target object. Modify the signature to function(src, target), rename obj to src internally, and replace the line copy = {} with copy = target || {}. Now a use case could be clone(a, Object.create(new A())) if you know that you want your new object to have a new A as prototype, etc.
8 年多之前 回复
weixin_41568126
乱世@小熊 I think it is reachable. The instanceof operator works by checking the objects prototype chain (according to the Mozilla Javascript reference: developer.mozilla.org/en/JavaScript/Reference/Operators/Special/…). I suppose that someone could modify the prototype chain to no longer include Object. That would be unusual, but would cause the error to be thrown.
9 年多之前 回复
csdnceshi51
旧行李 In your clone function, is the throw new Error statement reachable?
9 年多之前 回复

An elegant way to clone a Javascript object in one line of code

An Object.assign method is part of the ECMAScript 2015 (ES6) standard and does exactly what you need.

var clone = Object.assign({}, obj);

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

Read more...

The polyfill to support older browsers:

if (!Object.assign) {
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }

      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);

        var keysArray = Object.keys(nextSource);
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}
csdnceshi50
三生石@ this will only perform a shallow "cloning"
大约 4 年之前 回复
csdnceshi64
游.程 Oh I see, thanks (I wasn't familiar with the arguments object before.) I'm having trouble finding Object() via Google... it's a typecast, isn't it?
4 年多之前 回复
weixin_41568134
MAO-EYE yesterday All the arguments are iterated and merged into one object, prioritizing properties from the last passed arg
4 年多之前 回复
csdnceshi64
游.程 Sorry for the dumb question, but why does Object.assign take two parameters when the value function in the polyfill takes only one parameter?
4 年多之前 回复

With jQuery, you can shallow copy with extend:

var copiedObject = jQuery.extend({}, originalObject)

subsequent changes to the copiedObject will not affect the originalObject, and vice versa.

Or to make a deep copy:

var copiedObject = jQuery.extend(true, {}, originalObject)
csdnceshi51
旧行李 The original question did not mention anything about jQuery, I assumed the OP wanted a vanilla Javascript solution.
2 年多之前 回复
csdnceshi72
谁还没个明天 deep copy worked for me...
接近 3 年之前 回复
csdnceshi74
7*4 According to stackoverflow.com/questions/184710/… , it seems that "shallow copy" just copy the reference of originalObject ,so why here says that ...subsequent changes to the copiedObject will not affect the originalObject, and vice versa... . Sorry that I was really confused.
接近 4 年之前 回复
csdnceshi52
妄徒之命 you probably meant angular.merge as angular.extend doesn't do deep copy.
接近 4 年之前 回复
csdnceshi76
斗士狗 in line with this, if you're using angular, you could use angular.extend - docs.angularjs.org/api/ng/function/angular.extend
4 年多之前 回复
weixin_41568183
零零乙 that's an amazing use of the .extend method, which is normally used in jQuery plugins for basically the same thing. Wow.
接近 6 年之前 回复
csdnceshi69
YaoRaoLov Just a note, this doesn't copy the proto constructor of the original object
6 年多之前 回复
csdnceshi64
游.程 Shaver - YES! That's it! Without option of deep copy it didn't work for me!
接近 7 年之前 回复
weixin_41568196
撒拉嘿哟木头 Yes, take a look at Garry's link above... Not only does John Resig answer the question (he created jQuery), but the ensuing comments are hilarious. :-D
8 年多之前 回复
csdnceshi77
狐狸.fox Yes, I found this link helpful (same solution as Pascal) stackoverflow.com/questions/122102/…
接近 9 年之前 回复
csdnceshi68
local-host Also useful to specify true as the first param for deep copy: jQuery.extend(true, {}, originalObject);
9 年多之前 回复
csdnceshi75
衫裤跑路 or even: var copiedObject = jQuery.extend({},originalObject);
9 年多之前 回复

In ECMAScript 6 there is Object.assign method, which copies values of all enumerable own properties from one object to another. For example:

var x = {myProp: "value"};
var y = Object.assign({}, x); 

But be aware that nested objects are still copied as reference.

csdnceshi56
lrony* Object.assign only makes shallow copies. Properties on the prototype chain and non-enumerable properties cannot be copied.
大约 2 年之前 回复
csdnceshi65
larry*wei Too much to be aware of XD
大约 2 年之前 回复
csdnceshi50
三生石@ top level functions seemed to be copied by reference as well...
3 年多之前 回复
csdnceshi53
Lotus@ A lightweight polyfill that adds this feature to IE can be found here: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
接近 4 年之前 回复
weixin_41568127
?yb? This is the same as @EugeneTiurin his answer.
4 年多之前 回复
weixin_41568110
七度&光 I think should be mentioned that this is not suported by IE except Edge. Some people still use this.
4 年多之前 回复
weixin_41568196
撒拉嘿哟木头 Also be aware that this will copy over "methods" defined via object literals (since these are enumerable) but not methods defied via the "class" mechanism (since these aren't enumerable).
4 年多之前 回复
csdnceshi67
bug^君 But be aware that this makes a shallow copy only. Nested objects are still copied as references!
4 年多之前 回复
weixin_41568184
叼花硬汉 Yeah, I believe that Object.assign is the way to go. It's easy to polyfill it too: gist.github.com/rafaelrinaldi/43813e707970bd2d77fa
4 年多之前 回复

Per MDN:

  • If you want shallow copy, use Object.assign({}, a)
  • For "deep" copy, use JSON.parse(JSON.stringify(a))

There is no need for external libraries but you need to check browser compatibility first.

csdnceshi66
必承其重 | 欲带皇冠 works like a charm!
大约 2 年之前 回复
csdnceshi63
elliott.david for Date, I would use moment.js since it has clone functionality. see more here momentjs.com/docs/#/parsing/moment-clone
2 年多之前 回复
csdnceshi79
python小菜 JSON method I noticed converts date objects to strings but not back to dates. Have to deal with the fun of time-zones in Javascript and manually fix any dates. May be similar cases for other types besides dates
2 年多之前 回复
csdnceshi71
Memor.の JSON.parse(JSON.stringify(a)) looks beautiful, but before using it I recommend benchmarking the time it takes for your desired collection. Depending on object size, this might not be the quickest option at all.
3 年多之前 回复

There are many answers, but none that mentions Object.create from ECMAScript 5, which admittedly does not give you an exact copy, but sets the source as the prototype of the new object.

Thus, this is not an exact answer to the question, but it is a one-line solution and thus elegant. And it works best for 2 cases:

  1. Where such inheritance is useful (duh!)
  2. Where the source object won't be modified, thus making the relation between the 2 objects a non issue.

Example:

var foo = { a : 1 };
var bar = Object.create(foo);
foo.a; // 1
bar.a; // 1
foo.a = 2;
bar.a; // 2 - prototype changed
bar.a = 3;
foo.a; // Still 2, since setting bar.a makes it an "own" property

Why do I consider this solution to be superior? It's native, thus no looping, no recursion. However, older browsers will need a polyfill.

csdnceshi79
python小菜 This misleads people... Object.create() can be used as a means for inheritance but cloning is nowhere near to it.
3 年多之前 回复
csdnceshi57
perhaps? Using Object.create() on a const works perfectly for creating failing test objects that only slightly diverge from passing data. Thanks for the pointer... :ba dum cha:
大约 4 年之前 回复
csdnceshi58
Didn"t forge For cloning...this literally has no advantage over making a new var with a reference...since all you're doing is making a new var with a prototype with a reference. It's not a clone at all. Change a prop on the original and the "new" one changes too. You may as well just say that var obj1 = {}; var obj2 = obj1; is the best way to clone an object. Cool...except that's NOT cloning an object and doesn't solve ANY of the problems that need to be solved via cloning an object...because it's still just a reference. Obscuring the reference to the prototype doesn't change that.
4 年多之前 回复
csdnceshi65
larry*wei What if the cloned object had a property called info and the info object has properties, including a weight property. Then assigning myclone.info.weight would modify the prototype, because it reads info from the prototype then assigns to the weight property of that.
4 年多之前 回复
weixin_41568208
北城已荒凉 I really don't care if this is cloning or whatever but I have totally forgotten this solution and was nearly going to use one of the answers above, and maybe, this answer might not be the answer for the question but it simply gives an alternative to clone an object. And BTW I really do thank you, you saved tons of data from my game
大约 5 年之前 回复
weixin_41568126
乱世@小熊 article explains the difference between referencing and cloning: en.wikipedia.org/wiki/Cloning_(programming). Object.create points to the parent's properties through references.That means if the parent's property values change, the child's will also change. This has some surprising side-effects with nested arrays and objects that could lead to hard-to-find bugs in your code if you're not aware of them: jsbin.com/EKivInO/2. A cloned object is a completely new, independent object that has the same properties and values as the parent, but isn't connected to the parent.
接近 6 年之前 回复
weixin_41568127
?yb? "clone" isn't defined anywhere. To me, this is cloning, not copying.
接近 6 年之前 回复
csdnceshi67
bug^君 Javascript: The good parts states it well: The prototype relationship is a dynamic relationship. If we add a new property to a prototype, that property will immediately be visible in all of the objects that are based on that prototype
接近 6 年之前 回复
weixin_41568196
撒拉嘿哟木头 I agree with you completely. I do agree as well that this is not cloning as might be 'intended'. But come on people, embrace the nature of JavaScript instead of trying to find obscure solutions that are not standardized. Sure, you don't like prototypes and they are all "blah" to you, but they are in fact very useful if you know what you're doing.
大约 6 年之前 回复
weixin_41568110
七度&光 Useful for "completing" object params in functions. Thanks! function (optsIn) { optsWork = Object.create(optsIn); optsWorks.foo = 'bar'; ... }
6 年多之前 回复
csdnceshi59
ℙℕℤℝ even if not asked, still interesting..
6 年多之前 回复
weixin_41568126
乱世@小熊 This is prototypal inheritance, not cloning. These are completely different things. The new object doesn't have any of it's own properties, it just points to the prototype's properties. The point of cloning is to create a fresh new object that doesn't reference any properties in another object.
6 年多之前 回复
csdnceshi77
狐狸.fox I agree with @MattBierner. This can be a very dangerous option if you just want a copy of an object. If you want inheritance, great, use it. But! Run the example code and look at foo at the very end. It looks like this: > foo; > Object {a: 3, a: 2}.
接近 7 年之前 回复
csdnceshi53
Lotus@ In addition to the major identified issues, this can be dangerous in more subtile ways. One easy way to see this: Object.keys(foo) = ['a'] while Object.keys(bar) = [] (getOwnPropertyNames however does work as expected in this situation but hasOwnProperty is also incorrect). Even just using objects as maps, I would be careful using this approach.
7 年多之前 回复
csdnceshi56
lrony* Note: Object.create is not a deep copy (itpastorn mentioned no recursion). Proof: var a = {b:'hello',c:{d:'world'}}, b = Object.create(a); a == b /* false */; a.c == b.c /* true */;
7 年多之前 回复

If you do not use functions within your object, a very simple one liner can be the following:

var cloneOfA = JSON.parse(JSON.stringify(a));

This works for all kind of objects containing objects, arrays, strings, booleans and numbers.

See also this article about the structured clone algorithm of browsers which is used when posting messages to and from a worker. It also contains a function for deep cloning.

weixin_41568183
零零乙 It doesn't gracefully work with Date so after JSON.parse( JSON.stringify(obj) ) Date will become ISO Date string and not a Date object.
2 年多之前 回复
csdnceshi52
妄徒之命 In my experience this is the only safe way that I know of to clone an object, where the clones do not hold any references to the original object. Won't work with functions. For dates, store the dates as strings and it will be fine.
3 年多之前 回复
csdnceshi77
狐狸.fox It seems like I can't get the JSON library of functions into Quartz Composer's implementation of Javascript. I wonder if other application scripting domains like Adobe Creative Suite scripting are also limited? How to add JSON functions to them?
3 年多之前 回复
weixin_41568110
七度&光 This was a good solution for me with an array of objects that have multiple child nodes. Good quick solution!
大约 4 年之前 回复
csdnceshi51
旧行李 I'm sorry, I thought I commented on a different answer, (I was on other browser and had to login and when I came back, I commented on yours :D sorry about that)
4 年多之前 回复
csdnceshi71
Memor.の Read the first words of my answer: "If you do not use functions within your object, ..."
4 年多之前 回复
csdnceshi51
旧行李 It doesn't work when objects have callable functions :/
4 年多之前 回复
weixin_41568127
?yb? doesn't work with dates in my Angular project
4 年多之前 回复
weixin_41568184
叼花硬汉 Perfect for my use case, thanks!
4 年多之前 回复
csdnceshi65
larry*wei 2016 update: This ought to now work in pretty much every browser being widely used. (see Can I use...) The main question now would be whether it is sufficiently performant.
4 年多之前 回复
csdnceshi76
斗士狗 A million votes up for this one!
4 年多之前 回复
csdnceshi58
Didn"t forge Does not work for sparse arrays a=[]; a[5]=10; JSON.parse(JSON.stringify(a))!==a
接近 5 年之前 回复
weixin_41568174
from.. Working perfectly fine for a stubs environment with Node.js objects :)
5 年多之前 回复
weixin_41568134
MAO-EYE if a is undefined it does not work.
5 年多之前 回复
csdnceshi56
lrony* This is fine for only simple structures, the prototype is not maintained. Use the answer to this question if you need a true clone like the question asked for.
接近 6 年之前 回复
csdnceshi73
喵-见缝插针 It would crap all over the JSON if the object has un-stringify-able things such as Infinity, undefined, etc. Try this object: a = { b: Infinity, c: undefined }
接近 6 年之前 回复
csdnceshi61
derek5. I just want to add an update to this for Oct. 2014. Chrome 37+ is faster with JSON.parse(JSON.stringify(oldObject)); The benefit of using this is that it's very easy for a javascript engine to see and optimize into something better if it wants.
接近 6 年之前 回复
csdnceshi71
Memor.の Any circular strcuture is a problem when cloning. Even if it would work: Would the recursive object be linked to the original or the cloned object!?
大约 6 年之前 回复
csdnceshi64
游.程 Does not work with circular structure.
大约 6 年之前 回复
csdnceshi70
笑故挽风 yes higher is better (it tricked me too the first time...). Here is the good comment in the thread: stackoverflow.com/questions/122102/…
6 年多之前 回复
csdnceshi71
Memor.の As I mentioned in my answer...
6 年多之前 回复
weixin_41568126
乱世@小熊 Hm... Scratch that. I assumed lower was better. It's weird that Object.clone is so slow. I thought it would be the fasted one...
6 年多之前 回复
weixin_41568126
乱世@小熊 In theory it have to be slower - you loop at least twice and you could do it once or even less for custom made function (where you know the structure). In practice it is still slower. Or am I missing something in the stats you linked? Seem like jQuery deep copy is faster.
6 年多之前 回复
csdnceshi70
笑故挽风 Why not optimal in terms of time and memory? MiJyn says: "The reason why this method is slower than shallow copying (on a deep object) is that this method, by definition, deep copies. But since JSON is implemented in native code (in most browsers), this will be considerably faster than using any other javascript-based deep copying solution, and may sometimes be faster than a javascript-based shallow copying technique (see: jsperf.com/cloning-an-object/79)." stackoverflow.com/questions/122102/…
6 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 Doesn't work for functions though.
6 年多之前 回复
csdnceshi60
℡Wang Yan You could always include JSON2.js or JSON3.js. You would need them for your app anyway. But I do agree this might not be the best solution, since JSON.stringify does not include inherited properties.
6 年多之前 回复
weixin_41568126
乱世@小熊 Note that this can only be used for testing. Firstly, it's far from optimal in terms of time and memory consumption. Secondly, not all browsers have this methods.
大约 7 年之前 回复

New answer to an old question! If you have the pleasure of having using ECMAScript 2016 (ES6) with Spread Syntax, it's easy.

keepMeTheSame = {first: "Me!", second: "You!"};
cloned = {...keepMeTheSame}

This provides a clean method for a shallow copy of an object. Making a deep copy, meaning makign a new copy of every value in every recursively nested object, requires on of the heavier solutions above.

JavaScript keeps evolving.

csdnceshi80
胖鸭 I was using Object.assign() before, but now indeed object spread syntax is supported in latest Chrome, Firefox (still not in Edge and Safari). Its ECMAScript proposal... but Babel does support it as far as I can see, so probably its safe to use.
接近 3 年之前 回复
csdnceshi75
衫裤跑路 so use {... obj} instead of [...obj];
接近 3 年之前 回复
csdnceshi80
胖鸭 as far as I see spread operator only works with iterables - developer.mozilla.org says: var obj = {'key1': 'value1'}; var array = [...obj]; // TypeError: obj is not iterable
3 年多之前 回复
csdnceshi51
旧行李 it doesn't work when you have functions defined on objects
3 年多之前 回复

OK, imagine you have this object below and you want to clone it:

let obj = {a:1, b:2, c:3}; //ES6

or

var obj = {a:1, b:2, c:3}; //ES5

The answer is mainly depeneds on which ECMAscript you using, in ES6+, you can simply use Object.assign to do the clone:

let cloned = Object.assign({}, obj); //new {a:1, b:2, c:3};

or using spread operator like this:

let cloned = {...obj}; //new {a:1, b:2, c:3};

But if you using ES5, you can use few methods, but the JSON.stringify, just make sure you not using for a big chunk of data to copy, but it could be one line handy way in many cases, something like this:

let cloned = JSON.parse(JSON.stringify(obj)); 
//new {a:1, b:2, c:3};, can be handy, but avoid using on big chunk of data over and over
weixin_41568196
撒拉嘿哟木头 Can you please give example of what big chunk of data would equate to? 100kb? 100MB? Thanks!
大约 2 年之前 回复

Interested in cloning simple objects :

JSON.parse(JSON.stringify(json_original));

Source : How to copy JavaScript object to new variable NOT by reference?

共22条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问