How to clone an object in JavaScript

http://www.mikitamanko.com/blog/2013/05/12/how-to-clone-an-object-in-javascript/

What is the most efficient way to clone an object in JavaScript?

Here is the wrong way that will not work properly

var obj1 = { a: 1, b: { c: {d: 2}, e: 3}},
	obj2 = {};
 
console.dir(obj1);
 
for(var key in obj1) {
	if(obj1.hasOwnProperty(key)) {
		obj2[key] = obj1[key];
	}
}
 
console.dir(obj2); // seems the same object, but NOT


obj2 will look the same as an obj1, but it’s not a clone (because we just copied references), let’s prove that:

var obj1 = { a: 1, b: { c: {d: 2}, e: 3}},
	obj2 = {};
 
for(var key in obj1) {
	if(obj1.hasOwnProperty(key)) {
		obj2[key] = obj1[key];
	}
}
 
obj1.b.c.d = 42; // Changed obj1
 
console.dir(obj2); // OOPS, changes of obj1 has been applied to obj2

So it’s not a clone.

Here is the most efficient “handmade” way to clone the object:

var obj1 = { a: 1, b: { c: {d: 2}, e: 3}},
	obj2 = {};
 
obj2 = JSON.parse(JSON.stringify(obj1));
 
obj1.b.c.d = 42; // Changed obj1
 
console.log(obj1);
console.dir(obj2); // cool, obj2 still the same


BTW, in production code it’s recommended to use this way:

var obj1 = { a: 1, b: { c: {d: 2}, e: 3}},
	obj2 = {};
 
obj2 = $.extend(true, {}, obj1); // jQuery extend method
 
obj1.b.c.d = 42; // Changed obj1
 
console.log(obj1);
console.dir(obj2); // cool, obj2 still the same


I think that it is the best way to clone the object (described above)

Here is the list of all possible ways to clone the object:

// jQuery deep copy:
var newObject = jQuery.extend(true, {}, oldObject); // 76% slower
// JSON
var newObject = JSON.parse(JSON.stringify(oldObject)); // 12% slower
// jQuery copy (not deep)
var newObject = jQuery.extend({}, oldObject); // 24% slower
// simple clone function
var newObject = clone(oldObject); // fastest way, first function, that will copy only references (seems to be completely wrong way)
// ES5 Object.clone
var newObject = Object.clone(oldObject); // 85% slower


Here is the link on benchmark http://jsperf.com/cloning-an-object/2

So, the best production way to clone the object is still jQuery deep copy (not due to the benchmarks, but it’s the most safe and recommended way)
Let’s dig into this, and take a look under the hood. Here it the source code of jQuery extend:
https://github.com/jquery/jquery/blob/master/src/core.js#L265

Here is the “core” part

for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];
 
				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}
 
				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray(src) ? src : [];
 
					} else {
						clone = src && jQuery.isPlainObject(src) ? src : {};
					}
 
					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );
 
				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}


So, let’s take a look at fully “handmade” function “clone”
Here is simplified similar function (but not the same)

<span style="font-size:14px;">function extend (target, other) {
  target = target || {};
  for (var prop in other) {
    if (typeof source[prop] === 'object') {
      target[prop] = extend(target[prop], source[prop]);
    } else {
      target[prop] = source[prop];
    }
  }
  return target;
}</span>


P.S.

somewhere I saw this way to clone the object

eval(uneval(o));

Please, do not even think about using of this. Eval is completely evil (Douglas Crockford will help you to find out the reason)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值