自知其无知
不懂,慢慢懂。
posts - 2,comments - 2,trackbacks - 0


<script>
     
   
// 一个有趣的现象,也是一个值得分析的区别:
   Object.extend = function (destination,source){
        
// 首先,这个循环很奇妙,这个 property 是什么? 数组下标?
        
        
for(property in source){
            
            destination[property] 
= source[property];
        }
        

        
return destination;
   }

   

   
// 那么这里的 Object.extend 与 Object.prototype.extend 的区别是什么?
   // Object.extend 是属于类本身,而 Object.prototype.extend 所定义的方法属于所有的继承类?
   Object.prototype.extend = function (object){
      
return Object.extend.apply(this,[this,object]);
   }


   
/*
      这里 extend 函数是为所有派生自 Object 的子类添加 extend 方法
      1. 你可以把 extend 理解为 Object 静态方法  ,也就是 Object.extend ,是 Object 本身独有的
      2. 是 Object 添加 extend 公用方法,而他本身就是调用 Object.extend() 的,然后使用 apply 使得
         调用函数执行范围在 object.prototype 里,而不是 Object 自己,否则以后从 Object 或其派生
         类创建出的实例得不到 extend 中传入的参数的,这里 apply 的第一个参数就是 Object.prototype
         第二个参数是第一个方法的参数
      3. 是 extend 方法的应用
    
*/


    
/*
      来写一个例子来验证说法是否正确:(也就是如果不用 apply ,那么以后从)
    
*/



   
// 验证循环的奇妙现象
   var arr = new Array("China","England","USA");
   
for(obj in arr){
      
      alert(obj); 
// output  "0","1","2" ,也就是数组的下标
   }


  
//定义一个抽象基类base,无构造函数 (严格的说,base 类是不能被实例化的,但是我们却可以不规范的实例化,比如 (1) 所示)
    function base(){}
    
    
/* 
       通过 base.prototype = {} 以及 base.prototype.oninit = function(){} 两种方式我们可以看到,prototype 本身就
       是一个对象,而一个对象的赋值方式可以有两种形式,一种,就是用 key : value 的形式,也就是
       base.protype = {
         key : value 
       }
       而另一种形式就是 直接赋值的形式,也就是  base.protype.key = value 
       也就是说 obj = {
           key : value
        }
        和 obj.key = value 
        是等价的
     
*/

    base.prototype
={
          initialize:
function(){
                   
this.oninit(); //调用了一个虚方法 
          }

    }
  

    
/*****  base 类不规范的实例化(解释性的语言就是这样,呵呵) ********/
    
/*  
    base.prototype.oninit = function (){
        alert('方法 oninit() 被调用');
    }
    
*/

  
//  var ba = new base(); // base 被实例化了(关键点是,只要在调用的时候,oninit()方法被定义出来了就行!)
    
    
// 让一个 class 继承于 base 并实现其中的 oninit 方法
    function class1(){}
    
    class1.prototype 
= (new base()).extend(
        
{
            oninit : 
function (){  // 实现抽象基类的 oninit 虚方法           
                    // oninit 函数实现
            }

        }

    );
    
    
var cs = new class1();
    alert(cs 
instanceof base);    //  竟然能够 ouput "true"
    /*   */
   
/* 这样,当在 class1 实例中调用继承得到 initialize 方法时,就会自动执行派生类中的 oninit() 方法。
      从这里也可以看到解释型语言执行的特点,它们只有运行到某一个方法调用时,才会检查该方法是否存在,
      而不会像编译型语言一样,在编译阶段就检查方法是否存在, JavaScript 中则避免了这个问题,当然,如
      过希望在虚类中添加虚方法的一个定义,也是可以的。只要在派生类中覆盖此方法即可.

      例如,定义一个抽象基类  base1,无构造函数
    
*/
 
    
function base1(){}
    base1.prototype 
= {
        initilize:
function(){
            
this.oninit();  // 这里调用了一个虚方法
        }
,
        oninit : 
function(){} // 虚方法是一个空方法,由派生类产生
    }

    
   
/**********************************************************************************/
   
/* 使用抽象类的示例:  */
   
/*
      仍然以 prototype-1.3.1 为例,其中定义了一个类的创建模型:
   
*/

   
// Class1 是一个全局对象,有一个方法 create ,用于返回一个类,
   var Class1 = {
      create : 
function (){
        
return function (){
            
this.initialize.apply(this,arguments);
        }

      }

   }

   
/*
       这里 Class1 是一个全局对象,具有一个方法 create,用于返回一个函数(类),可以用如下
       语法:
    
*/

    
var c1 = Class1.create();
    
/*
      这样定义类的方式就和定义函数的方式区分开来,使 JavaScript 语言更具备面向对象的特点。现在
      来看这个返回的函数(类):
      function (){
         this.initilize.apply(this,arguments);
      }
      这个函数也是一个类的构造函数,当 new 这个类的时候便会执行,他调用了一个 initilize() 的方法,
      从名字看来,是类的构造函数。从类的角度来看,它是一个虚方法,是未定义的。但这个虚方法的实现
      并不是在派生类中实现的,而是创建完一个类后,在 prototype 中定义的,例如 prototype 可以这样
      写:
      var c1 = Class.create();
      c1.protype = {
         initilize : function( userName ){
             alert('hello,' + userName);
         }
      }

      这样,每次创建类的实例的时候,initialize 方法都会得到执行。从而实现了将类的构造函数和类成员一起
      定义的功能。其中,为了能够给构造函数传递参数,使用了这样的语句。
      function (){
         this.initilize.apply(this,arguments);
      }

      实际上,这里的 arguments 是 function() 中所传进来的参数,也就是 new class1(args) 中传递进来的参数,
      现在要把 args 传递给 initilize ,巧妙的使用了 apply() ,注意不能写成:
      this.initilize(arguments);

      这是将 arguments 数组作为一个参数传递给 initilize() 方法,而 apply() 方法则可以将 arguments() 对象
      的元素作为一组参数传递过去,这是一个很巧妙的实现。
      尽管这个例子在 prototype-1.3.1 中不是一个抽象类的概念,而是类的一种设计模式。但实际上,可以把
       Class.create() 返回的类看做所有类的共同基类,它在构造函数中调用了一个虚方法 initilize ,所有继承
       于它的类都必须实现这个方法,完成构造函数的功能。它们得以实现的本质就是对 prototype 的操作.
     
*/


</script>
posted on 2008-12-07 18:23 CopyHoo 阅读(1550) 评论(0)  编辑  收藏 所属分类: JavaScript

只有注册用户登录后才能发表评论。


网站导航: