MST

星途 面试题库

面试题:分析JavaScript原型链继承的缺陷及如何优化

JavaScript的原型链继承是其重要继承方式之一,但存在一些缺陷。请深入分析这些缺陷,如共享属性问题等,并提出相应的优化解决方案,同时给出优化后的代码示例。
30.5万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

原型链继承的缺陷

  1. 共享属性问题
    • 分析:在原型链继承中,所有实例会共享原型对象上的属性和方法。如果原型对象上的某个属性是引用类型(如数组、对象),那么当其中一个实例对该属性进行修改时,其他实例的该属性也会受到影响。例如:
    function Parent() {
        this.names = ['John', 'Jack'];
    }
    function Child() {}
    Child.prototype = new Parent();
    let child1 = new Child();
    let child2 = new Child();
    child1.names.push('Tom');
    console.log(child2.names); // 输出: ['John', 'Jack', 'Tom']
    
    • 解决方案:可以通过使用构造函数绑定(借用构造函数)来避免共享引用类型属性。
  2. 子类无法向父类传参
    • 分析:在原型链继承中,由于Child.prototype = new Parent()这种方式,在创建子类实例时,无法向父类构造函数传递参数。比如父类构造函数需要接收一些初始化参数时,原型链继承就无法满足。
    • 解决方案:同样可以使用借用构造函数的方式,在子类构造函数内部调用父类构造函数并传递参数。

优化解决方案及代码示例

  1. 借用构造函数(解决共享属性和传参问题)
    function Parent(name) {
        this.name = name;
        this.names = ['John', 'Jack'];
    }
    function Child(name, age) {
        // 借用构造函数,向父类传参
        Parent.call(this, name);
        this.age = age;
    }
    // 修复原型关系
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
    let child = new Child('Tom', 20);
    child.names.push('Bob');
    let anotherChild = new Child('Jerry', 22);
    console.log(anotherChild.names); // 输出: ['John', 'Jack']
    console.log(child.name); // 输出: 'Tom'
    console.log(child.age); // 输出: 20
    
  2. 组合继承(融合原型链继承和借用构造函数继承的优点)
    function Parent(name) {
        this.name = name;
        this.hobbies = ['reading', 'traveling'];
    }
    Parent.prototype.sayName = function() {
        console.log('My name is'+ this.name);
    };
    function Child(name, age) {
        Parent.call(this, name);
        this.age = age;
    }
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
    Child.prototype.sayAge = function() {
        console.log('My age is'+ this.age);
    };
    let child1 = new Child('Alice', 25);
    let child2 = new Child('Bob', 28);
    child1.hobbies.push('swimming');
    console.log(child2.hobbies); // 输出: ['reading', 'traveling']
    child1.sayName(); // 输出: My name is Alice
    child1.sayAge(); // 输出: My age is 25