# ES6 以前
在 es6 以前 js 并没有专门的关键字可以实现继承特性,但是那时候我们又需要使用继承。于是就产生了一些方法可以实现继承的效果
# 构造函数继承
call 调用实现继承父属性。我们都知道 call
可以改变函数内 this
的指向,利用这个特性我们可以在子构造函数里面调用父构造函数,并利用 call
让父构造函数内的 this
指向子构造函数。这样就完成了继承操作
function Father(uname,age){ | |
this.name = uname; | |
this.age = age; | |
}; | |
function Son(uname,age){ | |
Father.call(this,uname,age); // 调用父构造函数,利用 call 传入自身的 this 实现继承 | |
} |
重点:让新实例的原型等于父类的实例。
特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
缺点:1、新实例无法向父类构造函数传参。
2、继承单一。
3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)
# 原型链继承
我们还可以通过让子构造函数的 prototype
指向一个父构造函数的实例的形式实现继承,不过需要注意的是在赋值完成后我们需要让 constructor
属性重新指回子构造函数
function Father(uname,age){ | |
this.name = uname; | |
this.age = age; | |
}; | |
Father.prototype.say = ()=> console.log('hello!'); | |
function Son(uname,age){ | |
this.name = uname; | |
this.age = age; | |
} | |
// Son.prototype = Father.prototype 若我们直接赋值,会导致 Son 的原型对象和 Father 的原型对象是同一个,在 Son 中修改原型对象同时也会修改 Father 的。所以这样赋值是错误的 | |
Son.prototype = new Father(); // 通过一个 Father 实例化对象可以间接访问到 Father 的 prototype | |
Son.prototype.constructor = Son; // 让 constructor 指回 Son 构造函数,不然其会指向 Father 构造函数 | |
let son = new Son('Asuka',16); | |
son.say(); //hello! |
# 组合继承
function Father(uname,age){ | |
this.name = uname; | |
this.age = age; | |
}; | |
function Son(uname,age){ | |
Father.call(this,uname,age); // 借用构造函数继承 | |
} | |
Son.prototype = new Father(); // 原型链继承 | |
const s11 = new Son('zhangsan',18) |
# ES6 以后
es6 中引入了 class
关键字同时也引入了 extends
关键字,利用这些关键字我们可以很轻易的实现继承。同时若我们想要调用父类的方法和属性只需要使用 super
关键字。
class Father{ | |
constructor(uname,age){ | |
this.name = uname; | |
this.age = age; | |
} | |
say(){ | |
console.log('hello!'); | |
} | |
} | |
class Son extends Father{ | |
constructor(uname,age,sex){ | |
super(uname,age); // 直接使用,调用父类 constructor. 一定要在 this 之前,不然 SyntaxError | |
this.sex = sex; | |
} | |
say(){ | |
super.say(); | |
console.log('hi!'); | |
} | |
} | |
let son = new Son('Asuhe',16,'male'); | |
console.log(son); //Son { name: 'Asuhe', age: 16, sex: 'male' } | |
son.say(); // hello! hi! |