JavaScript中原型对象、构造函数、与实例的关系

什么是原型对象?

      “我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。”

      --摘自人民邮电出版社出版的Nicholas C.Zakas著的《JavaScript高级程序设计》(第2版)

      上面提到的对象,就是原型对象,它的用途是“包含可以由特定类型的所有实例共享的属性和方法”。那么怎么才能访问到它呢?按照上面的说法,每个函数都有一个prototype 指针,这个指针指向了它的原型对象,所以我们可以通过函数的prototype属性来访问函数的原型对象。

      下面用程序来说明。

JavaScript代码:
    function SuperType(){}  
       
    document.write(SuperType.prototype);//[object Object]  

      可见函数SuperType的确存在一个prototype属性,其的确是指向了一个对象。但这个对象真是原型对象吗?怎么证明?上面不是说原型对象的用途是“包含可以由特定类型的所有实例共享的属性和方法”,既然如此,那我们就来看这个对象是不是真的有这个功能。

JavaScript代码
    function SuperType(){}  
            
     SuperType.prototype.name = 'Sam';//在SuperType.prototype指向的对象上增加了name属性  
          
     //在SuperType.prototype指向的对象上增加了sayName方法  
     SuperType.prototype.sayName = function() {  
              document.write(this.name);  
     };  
     SuperType.prototype.setName = function(name) {  
              SuperType.prototype.name = name;  
     };  
          
     var instance1 = new SuperType();  
     var instance2 = new SuperType();  
          
     instance1.sayName();//Sam  
     instance2.sayName();//Sam  
          
     instance1.setName('Luce');  
           
     instance1.sayName();//Luce  
     instance2.sayName();//Luce  

      当实例instance1调用setName()函数更改了SuperType.prototype.name的值后,instance2.sayName()也会输出Luce,说明SuperType.prototype指向的对象的确是“包含了可以由特定类型(这里是SuperType)的所有实例所共享的属性和方法”,所以由此可以得出结论:

      SuperType.prototype指向的就是SuperType的原型对象,也即是函数的prototype属性指向了函数的原型对象。 

 

      下面用程序来说明构造函数、实例和原型对象三者之间的关系。 

 

      首先是构造函数与实例之间的关系,实例就是通过调用构造函数创立的:

JavaScript代码:
    function SuperType(name){  
               this.name = name;  
               this.sayName = function(){  
                     document.write(this.name);      
              }  
     }  
          
     var instance1 = new SuperType("Sam");  
     instance1.sayName();//Sam  
          
     var instance2 = new SuperType("Luce");  
     instance2.sayName();//Luce  

      我们在构造函数里面定义了一个name属性和一个sayName()函数,当调用new SuperType()创建实例时,就会调用构造函数SuperType创建实例对象,同时为实例对象增加一个name 属性和一个sayName()方法(也即是把this换成了实例对象(如this.name换成了instance1.name),所以每个实例的name和sayName()方法都是独立的,注意和在原型对象上定义的 区别,在原型对象上定义是共享的)。

     

      构造函数与原型对象的关系。前面已经说过,构造函数中有一个prototype属性,该属性是一个指针,指向了它的原型对象,那原型对象呢?是不是在它里面也存在一个指针,指向构造函数呢?答案是的确如此。原型对象中有一个constructor属性,该属性指向了构造函数:

JavaScript代码

 

    function SuperType(){}  
          
    document.write(SuperType.prototype.constructor);//function SuperType(){}  
    document.write(SuperType.prototype.constructor == SuperType);//true  

      打印SuperType.prototype.constructor,输出的是构造函数的定义,而我们知道函数名只是一个引用,其指向函数所在的地址,所以通过SuperType.prototype.constructor和SuperType的比较,返回了true,所以SuperType.prototype.constructor和SuperType一样都指向了SuperType()函数,在这里即是指向了构造函数。

 

      最后是实例与原型对象的关系。前面的例子可以看到(最开始),实例可以访问到在原型对象上定义的属性和方法,那么我们就可以猜测,实例中肯定有一个指针指向了原型对象,的确如此,实例中有一个属性__proto__(IE中没有这个属性,所以不要在IE下测试),该属性指向了原型对象:

JavaScript代码:
    function SuperType(){}  
          
     var instance = new SuperType();  
     document.write(instance.__proto__ == SuperType.prototype);//true  

      SuperType.prototype指向了SuperType的原型对象,而instance.__proto__和SuperType.prototype比较返回了true,这就说明instance.__proto__也指向了SuperType的原型 对象。

 

     以上即是JavaScript原型对象的相关信息。

转载自http://www.iteye.com/topic/1128242  感谢原创作者分享。

posted @ 2017-09-21 10:42  恩恩先生  阅读(645)  评论(0编辑  收藏  举报