微信号:FrontDev

介绍:分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯

如何实现对象的深度克隆

2015-06-21 19:56 前端大全

(点击上方蓝字,可快速关注我们)


前端笔试或者面试的时候,很喜欢问的一个问题就是对象的深度克隆,或者说是对象的深度复制。其实这个问题说容易很容易,但是要说全面也挺不易。


要弄明白对象的克隆,首先要明白js中对象的组成。在js中一切实例皆是对象,具体分为原始类型和合成类型。原始类型对象指的是number、string、boolean等,合成类型对象指的是array、object以及function。


又或许你刚听说“深度克隆”这个词,简单来说,就是说有个变量a,a的值是个对象(包括基本数据类型),现在你要创建一个变量b,使得它拥有跟a一样的方法和属性等等。但是a和b之间不能相互影响,即a的值的改变不影响b值的变化。


直接赋值可好?


var a = 1;

var b = a;

a = 10;

console.log(b);

// 1

var a = 'hello';

var b = a;

a = 'world';

console.log(b);

// hello

var a = true;

var b = a;

a = false;

console.log(b);

// true


实践证明某些JavaScript的原始数据类型,如果要克隆直接赋值即可。


关于function的深度复制:查阅了一些资料,function的深度复制似乎和原始数据类型的深度复制一样。


var a = function() {console.log(1);};

var b = a;

a = function() {console.log(2);};

b();

// 1


本来我也是这么认为的,直到文章下出现了评论。思考后我觉得function和普通的对象一样,只是我们在平常应用中习惯了整体的重新赋值,导致它在深度复制中的表现和原始类型一致:


var a = function() {console.log(1);};

a.tmp = 10;

var b = a;

a.tmp = 20;

console.log(b.tmp);

// 20


于是乎对于function类型的深度克隆,直接赋值似乎并不应该是一种最好的方法(尽管实际应用中足矣)。那么如何克隆?可以参考文章下面的评论,不失为一种解决方案。


但是对象呢?


var a = [0, 1, 2, 3];

var b = a;

a.push(4);

console.log(b);

// [0, 1, 2, 3, 4]


显然与预期不符,为什么会这样?因为原始数据类型储存的是对象的实际数据,而对象类型存储的是对象的引用地址。上面的例子呢也就是说a和b对象引用了同一个地址,无论改变a还是改变b,其实根本操作是一样的,都是对那块空间地址中的值的改变。


于是我们知道了,对于基本的对象来说,不能只能用=赋值,思索后写下如下代码:


function deepClone(obj) {

var o = obj instanceof Array ? [] : {};

for(var k in obj)

o[k] = typeof obj[k] === Object ? deepClone(obj[k]) : obj[k];

return o;

}

var a = [[1, 2, 3], [4, 5, 6, 7]];

var b = deepClone(a);

console.log(b);


似乎可以解决一般的对象(包括Array)的深度克隆了,或许这儿会有疑问,new String(..)这类的也是对象啊,可是这样写你克隆不了啊…但是楼主觉得深度克隆的考点不在这里,可能在于:


  1. 原始数据类型的直接赋值

  2. function的exception

  3. 对象的深度克隆中Array类型的判断

  4. 克隆函数的递归调用



来自:韩子迟

链接:http://www.cnblogs.com/zichi/p/4568150.html




前端大全』分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯,相关职位。欢迎关注。


微信号:FrontDev

(长按上图,弹出“识别二维码”后可快速关注)




 
前端大全 更多文章 5个典型的JavaScript面试题(上) Limu:JavaScript的那些书 Web开发:我希望得到的编程学习路线图 JavaScript基础工具清单 常用排序算法之JavaScript实现
猜您喜欢 七牛娱乐产业支持计划,全面开放申请!(文末有福利) 从贝叶斯的角度看正则项 Hadoop启动报Error: JAVA_HOME is not set and could not be found解决办法 你还需要另一个周刊吗? Android相机开发那些坑