`

浅说javascript中的原型链

阅读更多
        浅尝原型链
        ECMAScript中的对象是一个无序属性的集合,其属性可以包含基本值、对象或者函数,它拥有一个prototype对象。
        一个对象的prototype是以内部的[[Prototype]]属性来引用的。对于prototype对象来说,我们使用__proto__(firefox,chrome)来表示。
       原型对象也是简单的对象并且可以拥有它们自己的原型。如果一个对象的原型是一个非null的引用,那么以此类推,这就是原型链。
       原型链窥视
       我们来看一个例子,看一个普通对象的整个原型链的结构。
var mike = {
 sex:"male",
 location:"beijing"
}
console.log(mike);
      下图是在chrome浏览器里的变量原型链结构:


 
      原型链结构图:



 
    分析:
     根据上图,我们可以看到定义的mike对象有两个自身属性sex和location,mike这个对象有个[[Prototype]]属性__proto__,指向了【Object的prototype对象】,该对象没有了内置的[[Prototype]]属性,它自带一个constructor属性,该属性指向【Object构造函数】,在【Object构造函数】中有prototype属性,该属性指回了【Object的prototype对象】,【Object构造函数】中有个__proto__属性指向了【Function的prototype对象】,该对象的constructor指向了【Function构造函数】,而其内的__proto__对象指向了【Object的prototype对象】,在【Function构造函数】中的prototype对象指回了【Function的prototype对象】,__proto__对象指向了【Object的prototype对象】。
      以上例子我们可以看到一个普通对象的整个原型链情况,那么原型链到底干嘛用的呢?
    原型链用处
    原型链是一个指针,指向一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。它的好处就是让所有对象实例共享它包含的属性和方法。
   共享属性和方法
function Person(){

}
Person.prototype.name='mike';
Person.prototype.location='beijing';
Person.prototype.sayHello=function(){
 console.log('Hello');
};

var mike = new Person();
console.log(mike);
var zeromike=new Person();
console.log(zeromike);
 

 
     我们可以看到在mike和zeromike两个对象中具有相同的属性和方法,这也是原型链最基本的用法。
     继承
     在ECMAScript中实现继承主要是依靠原型链来实现的。
     我们回顾一下构造函数,原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。如果让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针。相应地,另一个原型中也包含着一个指向另一个构造函数的指针。如果另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这是原型链的基本概念。我们就依靠这个概念来实现继承。
function SuperType(){
 this.property=true;
}
SuperType.prototype.getSuperValue = function(){
 return this.property;
}
function SubType(){
 this.subproperty=false;
}
SubType.prototype=new SuperType();
SubType.prototype.getSubValue=function(){
 return this.subproperty;
}
var instance = new SubType();
console.log(instance.subproperty);
   

   
       以上代码定义了两个类型:SuperType和SubType。每个类型分别有一个属性和一个方法。它们的主要区别是SubType继承了SuperType。而继承是通过创建SuperType的实例,并将该实例赋给SubType.prototype实现的。实现的本质是重写原型对象,代之以一个新类型的实例。换句话说,原来存在于SuperType的实例中的所有属性和方法,现在也存在于SubType.prototype中了。在确立了继承关系后,给SubType.prototype添加一个方法,这样就在继承了SuperType的属性和方法的基础上又添加了一个新方法。这个例子中的实例及构造函数和原型之间的关系如图:

       在上面的代码中,我们没有使用SubType默认提供的原型,而是给它换了新原型:这个新原型就是SuperType的实例。于是,新原型不仅具有作为一个SuperType的实例所拥有的全部属性和方法,而且其内部还有一个指针,指向了SuperType的原型。getSuperValue()方法仍然还在SuperType.prototype中,但property则位于SubType.prototype中。这是因为property是一个实例属性,而getSuperValue()则是一个原型方法。既然SubType.prototype现在是SuperType的实例,那么property当然就位于该实例中了。此外,要注意instance.constructor现在指向的是SuperType,这是因为原来SubType.prototype中的constructor被重写了的缘故。实际上,不是SubType的原型的constructor属性被重写了,而是SubType的原型指向了另一个对象SuperType的原型,而这个原型对象的constructor属性指向的是SuperType.
ITEYE的编辑器是我见过的最差的编辑器了。。。。
 
  • 大小: 25 KB
  • 大小: 235.7 KB
  • 大小: 15.2 KB
  • 大小: 11.2 KB
  • 大小: 606.7 KB
2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics