MST

星途 面试题库

面试题:JavaScript 中类与原型的继承关系

在JavaScript中,通过类(class)创建对象和基于原型(prototype)创建对象,这两种方式在继承上有什么联系和区别?请举例说明。
33.3万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

联系

  1. 本质相同:在JavaScript中,class本质上是基于原型的语法糖。无论是通过class还是直接基于prototype创建对象,最终都是利用原型链实现继承。例如:
// 基于原型创建对象
function Animal(name) {
    this.name = name;
}
Animal.prototype.speak = function() {
    console.log(this.name + ' makes a sound.');
};

// 基于class创建对象
class Dog extends Animal {
    constructor(name, breed) {
        super(name);
        this.breed = breed;
    }
    bark() {
        console.log(this.name + ' barks.');
    }
}

const dog = new Dog('Buddy', 'Golden Retriever');
dog.bark();
dog.speak();

这里Dog类继承自AnimalDog的实例dog可以访问Animal原型上的speak方法,无论是class语法还是原型写法,都是通过原型链实现这种继承关系。

区别

  1. 语法复杂度
    • class:语法更简洁、直观,更符合传统面向对象编程的习惯。比如上面Dog类定义时,使用extends关键字明确表示继承关系,constructor定义构造函数,整体结构清晰。
    • prototype:语法相对复杂,需要手动在构造函数的原型上添加属性和方法。例如Animal.prototype.speak = function() {... }这种写法,对于初学者理解和编写代码的难度相对较大。
  2. 函数声明方式
    • class:类的方法默认是不可枚举的。比如在上面Dog类中的bark方法,使用Object.keys(Dog.prototype)无法获取到bark方法名。
    • prototype:通过原型添加的方法默认是可枚举的。如Object.keys(Animal.prototype)会包含speak方法名。
  3. 构造函数的处理
    • class:必须使用new关键字调用构造函数,如果不使用new,会抛出错误。例如let cat = Dog('Tom', 'Siamese');会报错。
    • prototype:构造函数既可以使用new调用,也可能在某些错误使用场景下不使用new调用,且不会直接报错(虽然结果可能不符合预期)。例如function Cat(name) { this.name = name; }let cat = Cat('Tom');不会报错,但cat可能不是预期的Cat实例对象。