JavaScript的Prototype实现

JavaScript的Prototype实现

作者:Jeff.Yan(阎宏),BlueSwing.Liu(刘如鸿)

模式:

Prototype(原始模型模式或者原型模式)

定义:

通过给出一个原型对象来指明所要创建的对象的类型,然后用这个原型对象的方法创建出更多同类型的对象,原始模型模式属于对象的创建模式

JavaScript实现:

在Java语言中对象都继承自java.lang.Object,而java.lang.Object就提供了Clone的方法,只要实现接口Cloneable,即表示支持Clone,否则抛出异常。在这点JavaScript是非常接近的,所有的对象都是从Object继承,不过Object并不支持Clone的方法,但是我们可以通过自己对于JavaScript通过expanddo的形式实现Clone方法,这样日后所有的对象创建都实现了Clone方法。

因为JavaScript本身没有提供Clone的方法,同时对于对象的赋值如var a=new Object();var b=a,这样的代码a,b是指向同一对象的,要创建一个对象必须通过 new 这个关键字来实现,因此在Clone的实现过程,我内部定义了一个构造子(constructor)CloneModel,同时指定其父对象为要进行Clone活动本身的对象,因此使用了 this关键字,在我们定义的构造子CloneModel的基础上我们创建一个一个对象,因为构造子内部没有任何代码,新创建的对象实际上说所有的实现都在父对象中,也就是我们需要进行Clone的对象。到目前为止,我们已经创建了一个需要复制的对象,但是所有的值都是指向父对象的。

在 JavaScript的面向对象方式中 ,我们曾经讨论过,如果没有覆盖父对象的值,那么这个时候是直接指向父对象的,在Prototype Pattern是要求Clone之后的对象的内部值是不应该相关的,而只要赋值一次,objClone的值都会在自己的内存空间里头,而不是还指向父对象。基于如此的考虑,objClone[v]=objClone[v];语句就是实现将父对象的值通过覆盖的方式拷贝到自己的内存来。(这里提及的内存应该是逻辑意义上的)

深复制的实现

在完成上述工作之后,只是实现了浅复制,对象方面依然是指向对象的引用,这个时候可以通过调用指向对象的Clone方法得到cloned对象的属性对象(因为不知道如何说了)。objClone[v]=objClone[v].Clone(); 这句代码就是完成如此的功能。

Clone方法的实现

//////////////////////////////////////////////////////////////////////
//为Object添加Clone的方法,因为所有的对象的顶级对象都是Object
//因此所有用户自定义对象都实现了Clone的方法
//////////////////////////////////////////////////////////////////////
Object.<b>prototype</b>.Clone=<b>function</b>(){
 <b>function </b>CloneModel(){

 }
 CloneModel.<b>prototype</b>=<b>this</b>;
 <b>var </b>objClone=<b>new  </b>CloneModel();

 <b>var </b>strMsg="";
 <b>for</b>( v <b>in </b>objClone){
  <b>switch </b>(<b>typeof </b>objClone[v]){
   <b>case </b>"function":
    //&#x5982;&#x679C;&#x662F;&#x65B9;&#x6CD5;&#xFF0C;&#x4E0D;&#x9700;&#x8981;&#x8FDB;&#x884C;clone
    <b>break</b>;
   <b>case </b>"object":
   ///////////////////////////////////////////////////////////////////////
   //&#x5982;&#x679C;&#x662F;&#x5BF9;&#x8C61;&#xFF0C;&#x91C7;&#x7528;Clone&#x91CD;&#x65B0;&#x5F97;&#x5230;&#xFF0C;&#x8FD9;&#x6837;&#x505A;&#x7684;&#x76EE;&#x7684;&#x5728;&#x4E8E;&#x80FD;&#x591F;&#x8FDB;&#x884C;&#x6DF1;&#x5EA6;Clone
   //&#x56E0;&#x4E3A;JavaScript&#x662F;&#x4E00;&#x4E2A;Object Based&#x7684;&#x8BED;&#x8A00;&#xFF0C;&#x4E0D;&#x7136;&#x5185;&#x90E8;&#x5BF9;&#x8C61;&#x662F;&#x6307;&#x5411;&#x539F;&#x6765;&#x7684;&#x5F15;&#x7528;
   ///////////////////////////////////////////////////////////////////////
    objClone[v]=objClone[v].Clone();
    <b>break</b>;
   <b>default</b>:
   ///////////////////////////////////////////////////////////////////////
   //&#x5176;&#x4F59;&#x6570;&#x636E;&#x7C7B;&#x578B;&#x60C5;&#x51B5;&#x4E0B;&#x5168;&#x90E8;&#x91CD;&#x65B0;&#x8D4B;&#x503C;
   //&#x8FD9;&#x6837;&#x505A;&#x7684;&#x76EE;&#x7684;&#x5C31;&#x662F;&#x4FDD;&#x8BC1;&#x6570;&#x503C;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x7684;&#x5B58;&#x653E;&#x662F;&#x5728;&#x65B0;&#x5BF9;&#x8C61;&#x7684;&#x7A7A;&#x95F4;&#x4E2D;
   //&#x800C;&#x4E0D;&#x4EC5;&#x4EC5;&#x6307;&#x5411;Parent Object&#x7684;&#x4E00;&#x4E2A;refrence
   ///////////////////////////////////////////////////////////////////////
    objClone[v]=objClone[v];
  }
 }
 <b>return </b>objClone;
}

对象类的定义

<b>function </b>BookInfo(vCaption){
 <b>this</b>.Caption=vCaption;
 <b>var </b>curPage=0;
 <b>this</b>.setPage=<b>function</b>(vData){
  curPage=vData;
 }
 <b>this</b>.getPage=<b>function</b>(){
  <b>return </b>curPage;
 }
}

测试代码

//////////////////////////////////
//test BookInfo 's clone method
//
//////////////////////////////////
<b>function </b>test(){
 <b>var </b>objTest=<b>new </b>BookInfo("JavaScript Prototype Pattern");
 objTest.setPage(1000);

 objTest.Author="Ruhong.Liu"; //object expanddo

 ShowObject(objTest,"&#x539F;&#x59CB;&#x5BF9;&#x8C61;");
 //Clone Object from objTest
 <b>var </b>objCloned=objTest.Clone();
 ShowObject(objCloned,"Clone&#x4E4B;&#x540E;&#x7684;&#x5BF9;&#x8C61;");
 //if you changed the objTest's caption
 //you can find objCloned's caption has be changed
 objTest.Caption="Changed Base Object";
 //show message
 ShowObject(objTest,"&#x4FEE;&#x6539;Caption&#x4E4B;&#x540E;&#x7684;&#x539F;&#x59CB;&#x5BF9;&#x8C61;");
 ShowObject(objCloned,"&#x4FEE;&#x6539;Caption&#x4E4B;&#x540E;&#x7684;clone&#x5BF9;&#x8C61;");

/*
 //----------&#x8FD9;&#x6BB5;&#x4EE3;&#x7801;&#x53EF;&#x4EE5;&#x4E0D;&#x5DE5;&#x4F5C;------------------------//
 //now you can change objCloned's caption
 objCloned.Caption="hello,Jeff.Yan";
 //show message
 ShowObject(objTest,"Clone&#x5BF9;&#x8C61;Caption&#x4FEE;&#x6539;&#x4E4B;&#x540E;&#x7684;&#x539F;&#x59CB;&#x5BF9;&#x8C61;");
 ShowObject(objCloned,"Clone&#x5BF9;&#x8C61;Caption&#x4FEE;&#x6539;&#x4EE5;&#x540E;");
*/
}
<b>function </b>ShowObject(o,vCaption){
 <b>var </b>strMsg=vCaption +"\n";
 strMsg+="CurrentPage:        " + o.getPage() +"\n";
 strMsg+="Caption:         " + o.Caption +"\n";
 strMsg+="Expanddo Property Author:       " + o.Author;
 alert(strMsg);
}

结束语:

按照我目前的理解和测试,我觉得prototype关键字不是prototype模式的实现,这点通过parent object可以得到验证。

作者Blog: http://blog.csdn.net/liuruhong/

相关文章
战争与和平——纵观浏览器发展二三语 越过浏览器开发的鼎盛时期,迎接RIA时代的到来 Longhorn时代,浏览器的终结?——关于Avalon和XAML C++/CLI会冲击C#吗? 在较量中携手前行——写给Java 1.5和.NET 2.0

对该文的评论
( )__( )__( )__( )__( )

Original: https://www.cnblogs.com/sunsonbaby/archive/2005/02/02/101161.html
Author: 笨笨
Title: JavaScript的Prototype实现

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/536006/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球