‘继承’是面向对象里面的概念,看下维基百科如何介绍继承:
如果一个类别B“继承自”另一个类别A,就把这个B称为“A的子类”,而把A称为“B的父类别”也可以称“A是B的超类”。继承可以使得子类具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类的行为在编译期就已经决定,无法在运行期扩展。
维基百科并没有说继承是什么,而只是描述了继承的作用,由上可知,继承是两个类之间的关系。
但是JS中并没有类,我们只能通过构造函数去构造实例对象,而实例的共有有属性与方法是部署在构造函数的prototype属性上的。我们知道,JS中存在原型链,也就是说每一个对象都有他的原型,原型也是对象,所以也有它的原型,如果调用一个对象的属性或者方法,他自身没有定义,就会去它的原型链上找,先找原型再找原型的原型......,这有就是为什么所有对象都会拥有valueOf方法,因为在原型链的上层是Object.prototype对象,valueOf方法是部署在它上面的,所以可以看做它们继承自Object.prototype对象。这样说并不恰当,因为JS中没有类,没有类怎么实现继承呢?所以JS语言的继承不通过类,而是通过“原型对象”(prototype)实现的。
在JS中如何根据某些需要手动去实现继承呢?也就是说在原型链上插一脚,让一个原型对象拥有另外一个原型对象的属性和方法?见下例:


由上可见,b对象是B的实例,b不仅仅具有B部署的它的实例自身属性,也具有A部署的它的实例自身属性,而且b的原型链上出现了A.prototype上部署的方法。
如果对象b调用method1方法,因为method1是部署在A.prototype对象上的,所以b的method1方法就是继承自A.prototype。
有一点需要注意,如果对象b调用b.constructor方法,是不是也是继承呢?不是,因为constructor方法定义在它的构造函数B的prototype属性上,b是B的实例,所以constructor是实例的方法。
但是这样修改原型链是不好的,因为更改__proto__属性非常消耗浏览器的性能,并且兼容性不好,因为有些浏览器不会让你去修改这个属性。而且这个特性已经在web标准中废除了,所以我们可以这样去做:

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。 这样做是非常好的,但是注意,B.prototype.constructor方法消失了,该方法指向与之对应的构造函数,所以我们还要加一句:

还有一种古老方法也是可行的:

另外ES6提供的新语法提供了新的解决方案,更加简洁容易,但是我不喜欢。见下图:

ES6中实现继承需注意以下几点:
①,class关键字与extends关键字
②,constructor函数中必须用调用super函数来让子类实例具有超类实例自身的属性,且要在this前面调用。
③,只能给子类的prototype对象添加方法,不能直接添加属性,不然报错。
网友评论