JavaScript的Prototype(原型)方式实现

Design Pattern 专栏收录该内容
1 篇文章 0 订阅

写在前面:
    这是我前段时间和Jeff.Yan的一些讨论搞,主要关于JavaScript的Design Pattern,因为没有整理,都是最原始的email内容,我会陆续的贴出一点我给他信,至于他的一些回答和讨论的结果,我会在征求他本人意见的情况下,尽可能完整的贴出来

    因为是和Jeff.Yan的讨论稿,对于我发信内容的发表都同时署名,对于他给我的回信,如果征得他本人同意的情况下在文字中我依然会特别说明。


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.prototype.Clone=function(){
 function CloneModel(){
  
 }
 CloneModel.prototype=this;
 var objClone=new  CloneModel();
 
 var strMsg="";
 for( v in objClone){ 
  switch (typeof objClone[v]){
   case "function":
    //如果是方法,不需要进行clone
    break;
   case "object":
   ///
   //如果是对象,采用Clone重新得到,这样做的目的在于能够进行深度Clone
   //因为JavaScript是一个Object Based的语言,不然内部对象是指向原来的引用
   ///
    objClone[v]=objClone[v].Clone();
    break;
   default:
   ///
   //其余数据类型情况下全部重新赋值
   //这样做的目的就是保证数值在内存中的存放是在新对象的空间中
   //而不仅仅指向Parent Object的一个refrence
   ///
    objClone[v]=objClone[v];
  }   
 }
 return objClone;
}
 
对象类的定义

function BookInfo(vCaption){
 this.Caption=vCaption; 
 var curPage=0;
 this.setPage=function(vData){
  curPage=vData;
 }
 this.getPage=function(){
  return curPage;
 } 
}
 
测试代码

//
//test BookInfo 's clone method
//
//
function test(){
 var objTest=new BookInfo("JavaScript Prototype Pattern");
 objTest.setPage(1000);
 
 objTest.Author="Ruhong.Liu"; //object expanddo
 
 ShowObject(objTest,"原始对象");
 //Clone Object from objTest
 var objCloned=objTest.Clone();
 ShowObject(objCloned,"Clone之后的对象"); 
 //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,"修改Caption之后的原始对象");
 ShowObject(objCloned,"修改Caption之后的clone对象");
 
 
/*
 //----------这段代码可以不工作------------------------//
 //now you can change objCloned's caption
 objCloned.Caption="hello,Jeff.Yan";
 //show message
 ShowObject(objTest,"Clone对象Caption修改之后的原始对象");
 ShowObject(objCloned,"Clone对象Caption修改以后");
*/ 
}
function ShowObject(o,vCaption){
 var 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可以得到验证。
  • 0
    点赞
  • 7
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值