JS中的克隆

前两天面试的时候,面试官问了一个关于js中克隆继承的问题,当时一脸懵逼,这也算是基础掌握不扎实吧。下来在网上搜了一下,有很多相关的问题,看来这也是一个面试中常遇到的问题。

一、什么是克隆?

克隆分为浅克隆和深克隆,浅克隆是指对象中的原始数据类型按值传递,而对象类型仍为引用传递。深克隆是指把原对象里的东西完全复制一份,但是这两个对象分别存在在不同的内存地址,因此对于新对象的修改不会影响到原对象。

这里有牵扯到了js中的数据类型,顺便说一下。js中的数据类型分为:原始类型和对象类型。其中,原始类型有五种,包括:Number,String,Boolean,Null,Undefined。对象类型主要是指两种特殊的对象:函数和数组。原始类型中保存的是变量的实际数据,而对象类型中保存的是对象的引用地址。因此,在对这两种类型的数据进行克隆的时候就会出现差异。

二、浅克隆

想象一个场景:我们希望给每一个注册用户建立一个数据模型,在此之前,我们要把这个用户的数据模型模板给创建出来:

JS中的克隆
用户模板

以后每个注册用户都会根据这个模板来生成对象。可以说这个userTemplate就是父对象了。

现在来了一个新用户来注册,用这个模板对象复制一个新对象来,我们可以写一个函数,把userTemplate对象的每一个属性都复制到这个新对象里,代码是这样的:

JS中的克隆
给标签属性增加一个标签,光头

然后我们又来了一位用户,我们可以同样用刚才写的函数新复制一个对象:

JS中的克隆
给苍井空加一个辣妹的标签

这三个对象打印的结果分别是这样的:

JS中的克隆
三个对象的数组属性是有问题的。

结果傻逼了,数组属性出现了问题,3个对象的数组属性都一样。

这很好理解,因为简单的复制对象,如果对象其中一个属性是引用型变量,就会出现这种情况,因为引用型变量保存的是内存地址,所以其实后来操作的都是同一块内存,导致了数组内容都一样。这就是浅克隆。

三、深克隆

深克隆是什么?深克隆就是在克隆的时候判断一下属性的类型是不是引用型变量,如果是的话就用递归方法让它一层一层进去复制自己。代码如下面所示。对于数组Array用typeof得到的也是'object',因此为了精确得到数据类型,这里用到了一个constructor的方法,通过判断构造函数来判断数据类型。还可以使用对象的tostring方法,为了避免tostring方法被改写,最好使用Object原型上的tostring方法:Object.prototype.tostring.call(obj[i]);如果是数组得到的是[object Array],对象得到的是[object Object],函数得到的是[object Function],通过截取字符串就可以得到精确的数据类型:Object.prototype.tostring.call(obj[i]).slice(8,-1)。

JS中的克隆
递归深度克隆代码

然后用这个新写的函数去复制对象,重新让郭德纲和苍井空两位老师注册一下。

JS中的克隆
用深度克隆的方法来克隆对象。

这样的话再打印出来看看:

JS中的克隆
一切正常了。

这就是深度克隆了,它其实也是js的继承的方法的一种。

参考地址:http://blog.csdn.net/hexon804/article/details/51323584http://www.2cto.com/kf/201409/332955.html