面试题答案
一键面试内在联系
- 原型链基础:无论是传统基于
prototype
的继承还是 ES6class
继承,本质上都依赖原型链来实现继承。在传统方式中,通过设置prototype
属性来构建原型链;ES6class
继承同样基于原型链,class
只是语法糖,其背后的实现依旧是原型链机制。例如:
// 传统方式
function Animal() {}
Animal.prototype.eat = function() {};
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// ES6 class 方式
class Animal {
eat() {}
}
class Dog extends Animal {}
在这两种方式下,Dog
实例的原型链最终都会指向 Animal
的原型。
主要差异
- 语法
- 传统
prototype
方式:语法较为复杂和底层。需要手动创建构造函数,通过操作prototype
属性来设置原型和构造函数,如上述Dog
的继承实现。代码可读性相对较差,尤其是在处理多层继承时。 - ES6
class
方式:语法更加简洁、清晰和直观,类似于其他面向对象语言(如 Java、C#)的类继承语法。使用class
关键字定义类,extends
关键字实现继承,super
关键字调用父类的构造函数和方法。例如:
- 传统
class Parent {
constructor(x) {
this.x = x;
}
printX() {
console.log(this.x);
}
}
class Child extends Parent {
constructor(x, y) {
super(x);
this.y = y;
}
printY() {
console.log(this.y);
}
}
- 性能
- 传统
prototype
方式:在创建对象和构建原型链时,性能相对较低,因为涉及较多手动操作和中间步骤。例如创建中间的Object.create
操作,可能会带来一些额外的性能开销。 - ES6
class
方式:由于是语法糖,在性能上与传统prototype
方式基本相同。不过,现代 JavaScript 引擎针对class
语法进行了优化,在某些情况下可能会有更好的性能表现。但总体而言,两者性能差异不大,性能瓶颈通常在其他方面(如复杂计算、DOM 操作等)。
- 传统
- 原型链操作
- 传统
prototype
方式:开发者需要直接操作原型对象,如修改prototype
属性,手动设置构造函数等,这容易出错。例如,错误地修改原型对象可能会导致原型链混乱,影响继承关系。 - ES6
class
方式:对原型链操作进行了封装,开发者不需要直接操作原型对象。通过super
关键字来调用父类的构造函数和方法,使得原型链的管理更加安全和便捷。例如在子类构造函数中,必须先调用super()
才能使用this
,这保证了原型链的正确初始化。
- 传统