javascript设计模式交流(1)2010-02-04本文将讨论Prototype Pattern的js实现,之后讨论javascript的prototype继承和Prototype Pattern的关系。Prototype Pattern是一种创建型模式,在GoF Book中它的意图被描述成用原型 实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。Prototype Pattern本身实际上 非常简单,任何一个提供了clone()方法的对象都可以成为原型对象,所有通过它复制的对象都属于一类 对象。在静态语言中,这一模式被用于运行时指定对象类型,相比工厂模式,这一模式无需创建与类层 次平行的工厂类结构,实现上要方便得多。clone的三种js实现在js中,clone方法的实 现并不困难,对js的6种基本类型来说 string boolean undefined null number皆可直接用=赋值,唯一 麻烦的是object。对object 我们可以用clone其所有成员的方式复制 作为方法的函数可以这样 定义:/************************************/
function objectClone ()
{
var ret=new Object();
for(var p in this)
{
ret[p]=this[p];
}
return ret;
}但我们显然面对着一个 问题:this[p]也可能是一个object 所以很可能我们需要用递归来实现deepClonefunction objectDeepClone()
{
var ret=new Object();
for(var p in this)
{
if (typeof ret[p]!=object)ret[p]=this[p];
else ret[p] =objectDeepClone.call(this[p]);
}
return ret;
}对js来说 实现clone还有另外一种方式,在javascript中,构造器的 prototype属性指明了某一类的原型,当实例化时,这一原型被作为对象的原型使用。特别地,这个 prototype对象也可能是从某一原型构造出来的,这形成了一个类似继承的结构,所以javascript的面向 原型特性又被称作原型继承(尽管我很不赞同这种做法,还是要提一下)。回到我们前面的 Prototype Pattern,javascript天生的引用型原型继承为我们提供了另外一种clone的实现方式:function objectPrototypeClone()
{
var tmp=function(){};
tmp.prototype=this;
return new tmp;
}这样clone出来的对象只读地共享一个原型的属性,它的 最大优势是速度非常快,当我们希望快速复制大型对象时,可以使用这种方式,但是它会造成访问速度 降低,而且它实时反映父节点的变化。内置对象的clone但是,到这里为止,我们还没有 考虑内置对象,内置对象不能用普通方法clone 我们要考虑的内置对象有这么几个:Function Array String Boolean Number DateRegExp Error和Math没有需要clone的场景 所以不在我们的 考虑之中。对Function来说,完全产生一个副本是不可能的,因为我们无法保证构造的函数跟原 来的函数在同一作用域,但是不包含作用域的实现是很容易的:eval(this);或者使用 Function构造return Function(new String("return ")+this)();Function 本身是个Object 因此必须加上Object的clone 实现functionPrototypeClone需要一点小花招/************************************/
function functionClone()
{
var ret=Function(new String("return ")+this)();
for(var p in this)
{
ret[p]=this[p];
}
return ret }/************************************/
function functionDeepClone()
{
var ret=Function(new String("return ")+this)()
for(var p in this)
{
if(typeof ret[p]!=object)ret[p]=this[p];
ret[p]=objectDeepClone.call(this[p]);
}
return ret }/************************************/
function functionPrototypeClone()
{
var tmp=Function.prototype Function.prototype=this var ret=(new Function(new String("return ")+this))();
Function.prototype=tmp return ret }
/************************************/