javascript原型链及继承

150 阅读2分钟

一、要了解原型链,首先要了解什么是原型、以及有什么作用

我们创建的每个函数都有一个prototype属性(即原型对象指针),并且每个原型对象上都有一个constructor属性,该属性的指针指向原型对象所在的函数(函数本身)

    function Example(){}
    var example = new Example();
    example.prototype.constructor==Example  //true

使用原型的好处就是方便我们创建让所有对象实例都能共享属性和方法 

    // 创建一个构造函数
    function People(){}
    People.prototype.name = '路人甲';
    People.prototype.age = '29';
    People.prototype.getInfo = function(){
        return this.name+'今年'+this.age+'岁了';
    }
    var people1 = new People(); //实例1
    people1.getInfo();     //打印出'路人甲今年29岁了'
    var people2 = new People(); //实例2
    people2.getInfo();          //打印出'路人甲今年29岁了' 

当一个构造函数创建一个实例后,对象实例有一个内部指针(proto)指向构造函数的原型对象

    function Person(){}     // 创建一个构造函数
    var p = new Person();   //此处p是构造函数Person的实例
    p.__proto__ == Person.prototype   //true,
    // (注:由于__proto__属性是非标准的,建议使用isPrototypeOf或   Object.getPrototypeOf方法验证)
    Person.prototype.isPrototypeOf(p);   //true
    Object.getPrototypeOf(p)==Person.prototype; //true

二、通过上面的说明,我们已经对原型有一些了解了,那么什么是原型链呢?

原型链简单点说,就是一个构造函数的实例通过赋值的方式赋给另一个函数的原型对象(prototype)实现的

    // 创建一个构造函数A
    function A(){}
        A.prototype.run = function(){
        return '我叫蜡笔小新,今年5岁';
    }
    // 创建一个构造函数B
    function B(){}
    //通过赋值的方式使构造函数B拥有了构造函数A的方法(也就是说存在于A实例中的所有属性和方法,也存在于B中了)
    B.prototype = new A();
    var b = new B();
    b.run();   //打印出'我叫蜡笔小新,今年5岁';

  当实例调用某个属性或方法的时候会执行一次查找,比如调用b.run()时候,会先执行三次查找:实例b->B.prototype->A.prototype,最后一步才找到该方法。

  前面说过实例对象有一个内部指针指向构造函数的原型对象,那么我们可以使用实例的内部指针(proto)来进一步了解原型链

    b.__proto__ == B.prototype   //true
    // 因为B.prototype继承了构造函数A,所以我们也能获取到构造函数A的原型对象
    b.__proto__.__proto__ == A.prototype ; //true 
    B.prototype.__proto__ == A.prototype; //true 
    // 在js中所有的引用类型都是Object的实例,故此我们可以可以根据原型链找到Object的原型对象(所有函数的默认原型都是Object的实例)
    b.__proto__.__proto__.__proto__ == Object.prototype //true 
    B.prototype.__proto__.__proto__ == Object.prototype //true 
    A.prototype.__proto__ == Object.prototype  //true