在面试中有几个经常会被问到的问题~比如闭包啦~作用域啦~继承啦~那今天我们就来看看继承是怎么实现的~
class 继承(ES6)
先上一个es6的版本
// 父类
class Super{
constroctor (r) {
this.r = r;
}
}
// 子类
class Sub extends Super{
constroctor (r) {
super(r);
this.color = 'red';
}
}
可以看出,es6的继承非常简洁。
Object.create实现类式继承(ES5)
下面是一段摘自MDN的继承代码
//Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info("Shape moved.");
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this); //call super constructor.
}
Rectangle.prototype = Object.create(Shape.prototype);
var rect = new Rectangle();
rect instanceof Rectangle //true.
rect instanceof Shape //true.
rect.move(1, 1); //Outputs, "Shape moved."
原型链
// 父类
function Super() {
this.prop = true;
}
Super.prototype.getSuperValue = function() {
return this.prop;
}
// 子类
function Sub() {
this.subProp = false;
}
Sub.prototype = new Super(); // 继承
Sub.protorype.getSubValue = function() {
return this.subProp;
}
原型链实现继承时存在两个问题:
-
引用类型的属性会被所有实例共享。
-
创建子类型实例时不能给超类型传参。
构造函数
在子类型构造函数内部调用超类型构造函数即可解决引用类型值的问题,同时还能向超类型传参。
function Super(name) {
this.colors = ['red',,'blue','green'];
this.name = name;
}
function Sub() {
Super.call(this, 'Sub');
}
构造函数的问题:
-
在超类型原型中定义的方法,对子类型是不可见的。
组合继承
将上两种方法组合在一起的方法。
function Super(name){
this.name = name;
this.colors = ['red',,'blue','green'];
}
Super.prototype.sayName = function() {
console.log(this.name);
}
function Sub(name, age) {
Super.call(this, name);
this.age = age;
}
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;
Sub.sayAge = function() {
console.log(this.age);
}
这也是是JavaScript最常用的继承模式。
原型式继承
function object(o) {
function F() {};
F.prototype = o;
return new F();
}
var Super = {
name : 'Super'
}
var Sub = object(Super);
在ES5可以将object()替换成Object.create(),用于没必要创建构造函数,只想一个对象和另一个对象保持相似的情况。和原型链模式一样,引用类型的属性会被共享。
寄生式继承
function createAnother(original) {
var clone = object(original); // 创建对象
clone.sayHi = function() { // 添加方法
console.log('Hi');
}
return clone;
}
var person = {
name: 'Nicholas'
}
var anotherPerson = createAnother(person);
这种方法和构造函数一样不能做到函数复用。
寄生组合式继承
之前说到组合继承是JavaScript中最常用的继承模式,但是使用时至少会调用两次超类型构造函数(call一次,new一次)。而使用寄生组合继承则不用:
function inheritPrototype(Sub, Super) {
var prototype = Object(Super);
prototype.constructor = Sub;
Sub.prototype = prototype;
}
function Super(name){
this.name = name;
this.colors = ['red',,'blue','green'];
}
Super.prototype.sayName = function() {
console.log(this.name);
}
function Sub(name, age) {
Super.call(this, name);
this.age = age;
}
inheritPrototype(Sub, Super);
Sub.sayAge = function() {
console.log(this.age);
}
寄生组合式继承避免了new操作再执行一次构造函数并在子类prototype上添加一些不必要的属性。
好啦~今天就到这啦~(≧▽≦)~