JavaScript继承

谈谈我对JavaScript继承的理解


发表一下我对于js继承的拙见,理解的深度比较浅,还望各位指点。

这里先写一个公共的父类

function Person (name, age) {
    this.name = name;
    this.age = age || 23;
    this.sayName = function () {
        console.log(`hello ${this.name}`)
    }
}

Person.prototype = {
    getAge: function () {
        console.log(`age: ${this.age}`);
    }
};

1、构造继承
把所有的属性和方法都放在构造函数内,在子类中调用父类的构造函数,相当于把父类的东西全部移到子类上

/**
 * 1、构造函数继承
 * @constructor
 */
function Man() {
    Person.call(this);
    this.sex = 'man';
}
var man = new Man();
console.log(man instanceof Man);// true,是子类的实例
console.log(man instanceof Person);// false,不是父类的实例
man.sayName();// 正常输出
man.getAge();// man.getAge is not a function,没有把原型链上的函数也添加到子类实例上

2、原型链继承
子类把所有属性和方法都放在原型链上,并把父类的实例放在子类的原型链上
原型链继承中,原型链上的方法和属性都是所有实例共享的,以为着你在实例A中修改原型链上的属性,实例B中也被修改了

function Man () {}
Man.prototype = new Person();
Man.prototype.getSex = function () {
    console.log(`sex ${this.sex}`);
};

var man = new Man();
console.log(man instanceof Man);// true,是子类的实例
console.log(man instanceof Person);// true,是父类的实例
man.sayName();// 正常输出
man.getAge();// 正常输出

3、组合继承
即同时使用构造函数继承和原型链继承。
构造函数继承父类的构造函数类的属性,原型链继承来继承原型链上的属性(一般是把属性放在构造函数内,保证每个子类实例的属性独立,把方法放到原型链上实现函数的复用)
唯一缺点是调用了两次父类构造函数(构造函数内一次,原型链上一次)

/**
 * 3、组合继承
 * @constructor
 */
function Man (name) {
    Person.call(this, name);
    this.sex = 'man';
}

Man.prototype = new Person();
Man.prototype.constructor = Man;
Man.prototype.getSex = function () {
    console.log(`sex ${this.sex}`);
};

var man = new Man();
console.log(man instanceof Man);// true
console.log(man instanceof Person);// true
man.sayName();// 正常输出
man.getAge();// 正常输出

4、寄生组合继承
最完美的一种继承,但是实现比较复杂,修复了组合继承的缺点

/**
 * 4、寄生组合继承
 * @param name
 * @constructor
 */
function Man(name) {
    Person.call(this);
    this.name = name;
}

function inherit(subType,superType){
    // 这个函数是最关键的
    // 定义一个空的类
    function F () {}
    // 把父类的原型链取出来
    F.prototype = superType.prototype;
    // 保存父类原型链
    let prototype = new F();
    /*---以上三行代码可以用ES5的这一行代码代替:var prototype=Object.create(superType.prototype); ---*/
    // 修正原型链的构造函数
    prototype.constructor = subType;
    // 把父类的原型链赋值给子类的原型链
    subType.prototype = prototype;
}

inherit(Man, Person);

var man = new Man();
console.log(man);
console.log(man instanceof Man);// true
console.log(man instanceof Person);// true
man.sayName();// 正常输出
man.getAge();// 正常输出

关于继承红宝书也说得很详细,这里再推荐一篇博文,写的也非常浅显→JS实现继承的几种方式
如果有什么问题还希望大家不吝赐教

猜你喜欢

转载自blog.csdn.net/tangjiahao1996/article/details/80070629