MST

星途 面试题库

面试题:JavaScript类继承中的多重继承模拟

JavaScript本身不支持多重继承,但可以通过一些技巧模拟多重继承。请设计一个方案来实现类似多重继承的效果,例如有`Flyable`和`Swimmable`两个“特性”类,创建一个`Duck`类同时具备飞行和游泳的能力,并说明你实现方案的原理和可能存在的问题。
12.5万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

实现方案

// Flyable “特性”类
function Flyable() {
    this.fly = function() {
        console.log('I can fly');
    };
}

// Swimmable “特性”类
function Swimmable() {
    this.swim = function() {
        console.log('I can swim');
    };
}

// Duck类通过多重继承获得Flyable和Swimmable的能力
function Duck() {
    Flyable.call(this);
    Swimmable.call(this);
}

// 辅助函数,用于继承原型方法
function extend(subClass, superClass) {
    function F() {}
    F.prototype = superClass.prototype;
    subClass.prototype = new F();
    subClass.prototype.constructor = subClass;
}

// Duck类继承Flyable和Swimmable的原型方法
extend(Duck, Flyable);
extend(Duck, Swimmable);

// 测试
const duck = new Duck();
duck.fly(); 
duck.swim(); 

原理

  1. 借用构造函数(call方法):在Duck构造函数内部,通过Flyable.call(this)Swimmable.call(this)调用FlyableSwimmable的构造函数,将FlyableSwimmable的实例属性复制到Duck实例上,这样Duck实例就拥有了flyswim方法。
  2. 原型链继承(extend函数):通过extend函数,让Duck的原型链继承自FlyableSwimmable的原型,这样Duck实例就可以访问FlyableSwimmable原型上的方法,即使是未来添加到原型上的方法也能访问。

可能存在的问题

  1. 属性重复:由于使用call方法将属性复制到Duck实例上,如果FlyableSwimmable中有同名的实例属性,会导致属性覆盖,后面调用的构造函数的属性会覆盖前面的。
  2. 原型链复杂:多次使用extend函数继承原型,会使Duck的原型链变得复杂,可能会增加查找属性和方法的时间,影响性能。同时,调试和理解代码也会变得更加困难。
  3. 方法重名冲突:如果FlyableSwimmable的原型方法中有同名的方法,同样会导致后面继承的方法覆盖前面的,可能会破坏预期的行为。