js继承一直是我觉得很神奇的地方,一年前看到这里的时候,其实是在死记硬背,只知道how to inherit,不知道why,而现在看到这里,我却想更多地了解它。
继承分为原型继承和构造函数继承。这里主要介绍原型继承。
原型继承的概念挖掘
原型继承就是把父类的一个实例赋值给了子类的原型,打破了子类原型原有的逻辑。子类原型的重写,在创建对象的篇幅中已经讲了——即用字面量形式创建原型属性。
这个时候,对于构造函数来说,它会有一个新的prototype,并且这个prototype的constructor是Object,因为此时,这个新的prototype也需要有一个自己的原型,来实现原型链。新的原型实质上是一个普通对象,它的[[prototype]]其实就是Object.prototype,而它的构造函数就是Object.prototype.constructor(即Object)。
而现在,我们用这种方式来实现继承,仍然是字面量形式,不过赋值的内容是一个对象实例,这个对象实例的原型有构造函数,构造函数又指向原型,整个流程是完整的。
我们这个弱小的实例(子类的原型)就偷偷拿到了整个的父类对象的内容。不管是父类的原型,还是父类实例所能访问到的内容。
这个时候,我们再去实现子类的实例,子类的实例会指向子类的原型。子类的原型又是父类的实例。那么,在访问属性或者方法的时候,子类的实例会先搜索自己实例内部有没有相应的方法,再去搜索子类的原型里有没有相应的方法(这里包括两部分,一部分是作为子类的原型所定义的方法,另一部分是作为父类实例所得到的构造函数中的属性),最后再去搜索父类的原型有没有相应的方法。
这也是原型链的本质。
原型继承中慎用字面量
根据以上描述,我们要知道:
- 子类继承了父类,我们利用了对象字面量的形式,在此之后,我们就不应该再次使用对象字面量创建任何方法和属性,因为我们会重写子类的原型,导致继承无效。
- 由于字面量赋值把一个对象的原型完全覆盖了,所以之前定义在字面量上的内容会统统失效。
字面量是一个很好的工具,它的破坏性也相当大。
但这并不是原型继承的问题。
原型继承的局限性
- 正如之前提到的,子类的实例继承了父对象,我们会发现,父对象实例中的属性会出现在子类的原型中,正如我们之前创建对象时的分析:
如果仅仅使用原型方法添加属性,会导致所有属性全局只有一份。普通属性还可以接受,但是引用类型的属性就不能接受了,比如一个数组,全局只有一份,一个改了,全都改了。
原型继承面对也是同样的问题,父类的属性出现在了子类的原型中,我们在创建子类实例的时候,子类的实例们会全局共享所有的原型属性。引用类型的属性则完全不能够私有,一个改了,所有的都变了。 - 子类无法向父类传递参数。
实例:
纯原型继承可以传参数的原型继承
网友评论