# 一、原型链继承
思路:将父类的实例作为子类的原型
缺点:
1.原型对象的所有属性被所有实例共享。(一个实例修改了原型属性,另一个实例的原型属性也会被修改)
2.在创建 Child 的实例时,不能向 Person 传参
function Parent () {
this.age = 50;
}
Parent.prototype.getAge = function () {
return this.age;
}
function Child() {
this.age = 25;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child
var c = new Child();
console.log(c.getAge())
# 二、借用构造函数继承
思路:直接利用call或者apply方法将父类构造函数的this绑定为子类构造函数的this
优点:
1.避免了引用类型的属性被所有实例共享
2.可以在Child中向Parent传参
缺点:
1.只能继承父类构造函数中的属性和方法,对于原型对象无法继承。
2.由于只能继承父类构造函数中的属性和方法,即方法都在构造函数中定义,无法实现函数复用
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
console.log(this.name);
}
function Child(name){
Person.call(this,name);
}
var child=new Child('小炮');
console.log(child.name)
# 三、组合继承
即组合原型链继承和借用构造函数继承。
思路:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承
特点:
1.可以继承父类原型上的属性,可以传参,可复用。
2.每个新实例引入的构造函数属性是私有的。
缺点:组合继承最大的问题就是无论什么情况下,都会调用两次父类构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部
function Person(name) {
this.name=name;
}
Person.prototype.getName=function (){
console.log(this.name);
}
function Child(name,age) {
Person.call(this,name);
this.age=age;
}
Child.prototype=new Person();
Child.prototype.constructor = Child;
var child = new Child('xiaopao',18);
child.getName();
console.log(child.age);
# 四、寄生组合式继承
即通过借用构造函数来继承属性,通过原型链的方式来继承方法,而不需要为子类指定原型而调用父类的构造函数,我们需要拿到的仅仅是父类原型的一个副本。因此可以通过传入子类和父类的构造函数作为参数,首先创建父类原型的一个复本,并为其添加constrcutor,最后赋给子类的原型。这样避免了调用两次父类的构造函数
function father(name) {
this.faName = "father";
}
father.prototype.getFaName = function () {
console.log(this.faName);
};
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function inheritPrototype(child, father) {
var prototype = object(father.prototype);
prototype.constructor = child;
child.prototype = prototype;
}
function child(args) {
this.chName = "child";
father.apply(this, []);
}
inheritPrototype(child, father);
child.prototype.getcnName = function () {
console.log(this.chName);
};
console.log(child.prototype.isPrototypeOf(new child())); //true
console.log(new child() instanceof child); //true
# 五、ES6中的继承
ES5的继承的实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面。ES6的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。可以通过extends
关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
class A {
constructor(name, age) {
this.name = name;
this.age = age;
}
getName() {
return this.name;
}
}
class B extends A {
constructor(name, age) {
super(name, age);
this.job = "IT";
}
getJob() {
return this.job;
}
getNameAndJob() {
return super.getName() + this.job;
}
}
var b = new B("Tom", 20);
console.log(b.name);
console.log(b.age);
console.log(b.getName());
console.log(b.getJob());
console.log(b.getNameAndJob());