面试经典问题,你讲讲原型链继承吧

190 阅读2分钟

每个人遇到这个问题,可能有不同的回答,但是回答的中心应该都是要首先简单阐述下什么是原型链(套娃链?), 然后就可以开始讲讲他继承的具体实现了。

什么是原型链呢

首先我们回顾一下  构造函数 , 原型对象 , 实例 三者的关系。 
我们知道 每个构造函数 都有一个 原型对象
         每个原型对象都有一个 constructor 指针指向构造函数
         每个原型都有一个 __proto__ 只想原型对象
         
         
假如我们让原型对象等于另一个类型的实例 ,那么此时原型对象的 __proto__指针将指向这个类型的原型对象
再假如这个类型(a)的原型对象又是另一个类型(b)的原型对象,那么此时a中的__proto__指针将只想b的原型对象
如此层层替进,就构成了示例与原型的链条,这就是原型链的基本概念

实现原型链的基本方式

```
    function Super () {
        this.Supervalue = true;
    }
    Super.prototype.getSupervalue = function(){
      return this.Supervalue;
    }
    function Subtype () {
      this.Subvalue = false;
    }
    Subtype.prototype = new Super();
    Subtype.prototype.getSubvalue = function () {
      return this.Subvalue
    }
    var ins = new Subtype();
    alert(ins.getSupervalue()); //true
    在这里定义了一个Super构造函数,通过创建Super实例,并将该实例赋给Subtype.prototype实现,本质就是重写原型对象
    然后我们通过Subtype实例化了一个ins,通过这个对象调用Super的getSupervalue方法,最终返回true就是通过原型链实现的,
    然后可能有同学想到了一个问题,Super的原型对象是谁呢?他也没有重写原型对象啊。
    其实,所有函数的初始原型对象都是一个Object实例,这也正是我们能使用toString 等方法的原因
```

原型与实例的关系

instanceof 操作符

alert(ins instanceof Subtype); //true
alert(ins instanceof Super); //true
alert(ins instanceof Object); //true
只要在ins的原型链上出现过的构造函数,都会返回true
那么也可以说 ins 是他们三个的实例

isPrototypeof

只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型
alert(Object.prototype.isPrototypeof(ins)) //true;

小心的定义原型方法嗷

通过原型链实现继承时,不能使用对象字面量创建原型方法,因为这样会重写对象原型链

原型链的问题

原型链用来继承也会有一些问题,最主要的来自引用类型值得原型。再通过原型来实现继承的时候,原型实际上会变成另一个类型的实例,实例属性自然也就变成了原型属性,那么相对于引用类型的属性来说,其某一实例修改引用类型的值,所有实例都会变化