前端面试题 - 40. ES5和ES6的继承? 这两种方式除了写法, 还有其他区别吗?

158 阅读2分钟

ES5的继承

通过原型链实现的

ES5的继承缺点是:

  • 原型链继承会导致所有的子类实例共享父类实例属性,当多个实例修改该属性时可能会互相影响。
  • 子类无法向父类传递参数。
function Animal(name) {
  this.name = name;
}
Animal.prototype.sayName = function() {
  console.log("My name is " + this.name);
};
function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
  console.log("Woof!");
};
const myDog = new Dog("Buddy", "Golden Retriever");
myDog.sayName(); // My name is Buddy
myDog.bark(); // Woof!
  • 解释 Animal.call(this, name)

Animal.call(this, name) 是将 Animal 构造函数的 this 绑定到 Dog 实例上,并传递参数 name 给 Animal 构造函数,以便在 Animal 构造函数中初始化 this.name 属性。 在 JavaScript 中,每个函数都是一个对象,都有一个 call 方法,这个方法可以用来调用一个函数,并指定函数中的 this 对象。在这个例子中,我们通过 call 方法将 Animal 构造函数中的 this 对象指定为 Dog 实例,这样 Animal 构造函数中的 this 就指向了 Dog 实例,从而在 Animal 构造函数中初始化的 this.name 属性就成为了 Dog 实例的属性。这样做的目的是让 Dog 实例继承 Animal 构造函数中初始化的属性。

  • 解释Dog.prototype = Object.create(Animal.prototype)

Dog.prototype = Object.create(Animal.prototype); 是将 Dog 的原型对象设置为一个新的对象,这个新的对象的原型是 Animal.prototype,也就是说,Dog 的原型对象继承自 Animal 的原型对象。 这样做的目的是让 Dog 的实例可以访问 Animal 的原型对象上的属性和方法,即 Dog 继承了 Animal 的原型属性和方法。例如,在上面的代码示例中,Dog 的原型对象继承了 Animal 的原型对象中的 sayName 方法,因此 Dog 的实例可以调用 sayName 方法,如 myDog.sayName()。 需要注意的是,Object.create() 方法返回一个新的对象,这个新的对象的原型是传入的参数,因此,Dog.prototype 不再是一个空的对象,而是一个继承自 Animal.prototype 的对象。由于 Dog.prototype 已经发生了改变,因此需要将 Dog.prototype.constructor 重新设置为 Dog,以保证 Dog 的实例可以正确地调用 Dog 的构造函数。

ES6的继承

通过类和 extends 关键字实现的。 ES6的继承相对ES5的继承,有以下优点:

  • ES6的继承方式更加清晰和易于理解,使用 extends 关键字明确表示子类继承自父类。
  • ES6的继承方式支持 super 关键字和构造函数,可以向父类传递参数和调用父类方法。
  • ES6的继承方式支持 classconstructor 关键字,提高了代码的可读性和可维护性。 因此,ES6的继承方式在设计上更加优秀,也更加符合JavaScript面向对象编程的实践。
class Animal {
  constructor(name) {
    this.name = name;
  }
  sayName() {
    console.log(`My name is ${this.name}`);
  }
}
class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }
  bark() {
    console.log("Woof!");
  }
}
const myDog = new Dog("Buddy", "Golden Retriever");
myDog.sayName(); // My name is Buddy
myDog.bark(); // Woof!