JS的多种继承方式

1. 原型链继承

将子类构造函数的原型指向父类的实例,可以继承父类的成员(属性和方法)以及父类原型链上的成员。

// 1. 对于继承的父类实例属性的引用值,为子类实例所共有,会产生篡改问题
// 2. 创建父类实例不传参数,子类会继承没有赋值的成员
function Father(lastName) {
    this.treasure = {
        name: "宝贝"
    }
    this.lastName = '尼古拉斯'
}
Father.prototype.sayHello = function() {
 	console.log("say hello")
}
function Son(name) {
    this.name = name
}
// 子类的prototype指向父实例
Son.prototype = new Father()
Son.prototype.constructor = Son
const son = new Son()
const son2 = new Son()
son.treasure.name = "垃圾"
console.log(son2.treasure)

2. 构造函数继承

子类构造函数中调用父类构造函数

// 优点:解决了引用类型值的原型属性会被所有实例共享
// 缺点:原型链上的共享方法和属性无法被继承,每创建一次子类实例都要调用一次父类构造函数
function Father(name, age) {
    this.name = name
    this.age = age
}
Father.prototype.sayHello = () => {
    console.log("say hello")
}
function Son(name, age, id) {
    Father.call(this, name, age)
    this.id = id
}
const s = new Son("张三", 18, 1001)
console.log(s)

3. 组合继承

结合了构造函数继承和原型链继承,既能继承原型链上的成员,又解决了引用类型值的实例间共享

// 缺点:父类的构造函数被执行两次,构造函数执行1次,创建原型执行1次
function Father(name, age) {
    this.name = name
    this.age = age
}
function Son(name, age, id) {
    Person.call(this, name, age)
    this.id = id
}
Son.prototype = new Father()
Son.prototype.constructor = Son
const s = new Son("张三", 18, 1001)
console.log(s)

4. 寄生组合继承

创建一个新的构造函数,将构造函数prototype指向父类构造函数的prototype,将该构造函数的实例作为子类的原型对象

function Father(name, age) {
    this.name = name
    this.age = age
}
function Son(name, age, id) {
    Father.call(this, name, age)
    this.id = id
}
function F() {}
F.prototype = Father.prototype
Son.prototype = new F()
// Object.create()的出现,不用再额外新建空白构造函数
// Son.prototype = Object.create(Father.prototype)
Son.prototype.constructor = Son
const s = new Son("张三", 18, 1001)

5. 多重继承

// 继承多个类
function Father(lastName, money) {
    this.lastName = lastName
    this.money = money
}
function Father2(skill) {
    this.skill = skill
}
function Son(lastName, money, skill, name ) {
    Father.call(this, lastName, money)
    Father2.call(this, skill)
    this.name = name
}
Son.prototype = Object.create(Father.prototype)
Object.assign(Son.prototype, Father2.prototype)
Son.prototype.constructor = Son

6. 圣杯模式继承

  • 补充:圣杯是宗教传说中的圣物,传说相信通过喝下圣杯中盛过的水,就能返老还童,死而复生并且获得永生。

  • 通过中间变量连接子类和父类

    // son.__proto__指向Son.prototype,就是new 出来的F的实例f
    // f.__proto__指向F.prototype 即 Function.prototype
    
  • 具体实现

    // 基础实现
    function inherit(target, origin) {
        // 使用新的API
        // const f = Object.create(origin.prototype)
        // target.prototype = f
    	function F() {}
        F.prototype = origin.prototype
        target.prototype = new F()
        target.prototype.constructor = target
        target.prototype.uber = origin.prototype
    }
    // 雅虎实现
    const inherit = (function() {
        const F = function() {}
        return function(target, origin) {
            F.prototype = origin.prototype
            target.prototype = new F()
            target.prototype.constructor = target
            // 通过uber可以找到该子类真正继承自哪个父类
            target.prototype.uber = origin.prototype
            // 如果需要使用构造函数,子类可访问父类构造函数绑定自身
            // target.prototype.uber = origin
        }
    }())
    function Father(lastName){
        this.lastName = lastName
    }
    Father.prototype.money = "100w"
    function Son(name) {
        this.name = name
    }
    inherit(Son, Father)
    Son.prototype.house = "500平"
    const son = new Son()
    const father = new Father()
    console.log(son.money)	// "100w"
    console.log(father.house)	// undefined
    

7. ES6 Class extend继承

class Father {
    static gender = '男'
    constructor(name, age){
        this.name = name;
        this.age = age;
        this.hobby = ["女"];
    }
    sayHi(){
        console.log('哈喽');
    }
}

class Son extends Father{
    constructor(name, age, id){
        super(name, age);
        this.id = id;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值