日期:2014-05-16  浏览次数:20354 次

clone的三种js实现

clone的三种js实现 ??

2009-11-17 08:37:54 |??分类: JavaScript技术 | 字号 ? 订阅

clone的三种js实现

在js中,clone方法的实现并不困难,对js的6种基本类型来说 string boolean undefined null number皆可直接用=赋值,唯一麻烦的是object。
对object 我们可以用clone其所有成员的方式复制 作为方法的函数可以这样定义:

Co

de:

???????? function clone()
???????? {
???????????????? var ret=new Object();
???????????????? for(var p in this)
???????????????? {
????????????????????????ret[p]=this[p];
???????????????? }
???????? }


但我们显然面对着一个问题:this[p]也可能是一个object 所以很可能我们需要用递归来实现deepClone


Code:
function deepClone()
???????? {
???????????????? var ret=new Object();
???????????????? for(var p in this)
???????????????? {
????????????????????????ret[p]=deepClone.call(this[p]);
???????????????? }
???????? }
??????

对js来说实现clone还有另外一种方式,在javascript中,构造器的prototype属性指明了某一类的原型,当实例化时,这一原型被作为对象的原型使用。特别地,这个prototype对象也可能是从某一原型构造出来的,这形成了一个类似继承的结构,所以javascript的面向原型特性又被称作原型继承(尽管我很不赞同这种做法,还是要提一下)。

回到我们前面的Prototype Pattern,javascript天生的引用型原型继承为我们提供了另外一种clone的实现方式:

Code:

???????? function prototypeClone()
???????? {
???????????????? var tmp=function(){};
????????????????tmp.prototype=this;
???????????????? return new tmp;
???????? }


这样clone出来的对象只读地共享一个原型的属性,它的最大优势是速度非常快,当我们希望快速复制大型对象时,可以使用这种方式,但是它会造成访问速度降低,而且它实时反映父节点的变化。

内置对象的clone

但是,到这里为止,我们还没有考虑内置对象,内置对象不能用普通方法clone 我们要考虑的内置对象有这么几个:
?????? Function Array String Boolean Number Date
RegExp Error和Math没有需要clone的场景 所以不在我们的考虑之中。

对Function来说,完全产生一个副本是不可能的,因为我们无法保证构造的函数跟原来的函数在同一作用域,但是不包含作用域的实现是很容易的:
?????? eval(this);
或者使用Function构造
?????? return Function(new String("return ")+this)();

Function本身是个Object 因此必须加上Object的clone 实现functionPrototypeClone需要一点小花招


Code:

???????? function functionClone()
???????? {
???????????????? var ret=Function(new String("return ")+this)();
???????????????? for(var p in this)
???????????????? {
????????????????????????ret[p]=this[p];
???????????????? }
???????? }
???????? function functionDeepClone()
???????? {
???????????????? var ret=Function(new String("return ")+this)()
???????????????? for(var p in this)
???????????????? {
????????????????????????ret[p]=deepClone.call(this[p]);
???????????????? }
???????? }
???????? function functionPrototypeClone()
???????? {????????????????
???????????????? var tmp=Function.prototype;
???????????????? Function.prototype=this;
???????????????? var ret=(new Function(new String("return ")+this))();
???????????????? Function.prototype=tmp;
???????????????? return ret;
???????? }


Array只要保证length正确就可以了


Code:

???????? function arrayClone()
???????? {
???????????????? var ret=new Array();
???????????????? for(var p in this)
???????????????? {
????????????????????????ret[p]=this[p];
???????????????? }
???????? }
???????? function arrayDeepClone()
???????? {
???????????????? var ret=new Array();
???????????????? for(var p in this)
???????????????? {
????????????????????????ret[p]=deepClone.call(this[p]);
???????????????? }
???????? }
???????