原型链是采用最主要的继承方式,
原理:每一个类(构造器,js中的function)都有一个原型属性(prototype)指向一个原型对象,原型对象有一个构造器(constructor),它又指回到function,是个循环引用,类的每个实例也有一个原型属性(代码无法访问,叫做_proto_),它跟构造器原型指向的是同一个对象,即同一个类的所有实例公用一个原型对象,要实现两个类型的继承,就是将一个类型的原型指向另一个类型的实例,而不再指定原来的默认的原型对象,这样就形成了原型链
子类可以通过原型链获得超类的所有属性和方法,从而实现了继承
实例:
function baseClass() { this.baseName = 'baseClass'; }
baseClass.prototype.getbaseClassName = function () { return this.baseName };
function childClass() { this.childName = 'childClass'; }
childClass.prototype = new baseClass();
childClass.prototype.getchildClassName = function () { this.childName; }
var instanse = new childClass();
instanse.getbaseClassName();
childClass(及它的实例)的prototype(_proto_)属性不在指向默认的prototype对象,而是Baseclass的实例,这个实例也有个属性(_proto_),它指向的是BaseClass的原型对象,在childClass的实例instanse上查找baseName属性的过程是这样:
首先在instanse自身找,但没找到,然后进入它的原型对象(_proto_属性,此时是BaseClass的实例,不再是默认的原型对象)依然没找到,则进入这个baseclass实例的原型对象(_proto_属性,默认的原型对象上找),终于找到,则返回这个方法的执行结果,
类的原型对象是所有实例共享的,这就造成一个问题,原型对象(父类实例)的属性和方法的改变将影响到所有实例,无论是创建的还是即将创建的
function baseClass() { this.Colors = ['bule', 'red']; }
function childClass() { }
childClass.prototype = new baseClass();
var instanse1 = new childClass();
var instanse2 = new childClass();
//在此实例上对从父类继承过来的属性进行修改
instanse2.Colors.push('green');
var instanse3 = new childClass();
///查看各个实例的colors属性值
alert(instanse1.colors);//red,blue,green
alert(instanse2.colors);//red,blue,green
alert(instanse3.colors);//red,blue,green
可见对于任一个实例来讲,如果修改了继承的属性值,则将影响任何时候创建的实例
另外如果继承的层次过多,则调用最顶层的效率最低