请梳理 JavaScript 中实现对象继承的主要方式,并说明各自的实现原理与适用场景。
考察说明
考查对 JavaScript 继承机制的掌握,包括原型链、构造函数、组合式继承等常见方式及其特点。
回答思路
- 【回答框架 1】原型链继承:通过将子类的原型指向父类实例实现,子类实例可访问父类原型上的属性和方法。缺点是所有实例共享父类实例的引用类型属性,且无法向父类构造函数传参。
- 【回答框架 2】构造函数继承:在子类构造函数中调用父类构造函数,通过 call 或 apply 绑定 this,解决了引用类型共享和传参问题,但方法无法复用,每个实例都有单独的方法副本。
- 【回答框架 3】组合继承:结合原型链和构造函数,既通过构造函数继承属性,又通过原型链继承方法,是常用的继承方式,但会调用两次父类构造函数,存在一定性能开销。
- 【回答框架 4】原型式继承与寄生式继承:基于已有对象创建新对象,利用 Object.create 或自定义函数实现,适合简单场景,但引用类型属性仍存在共享问题。
- 【回答框架 5】ES6 class 继承:通过 extends 关键字实现,语法更清晰,本质仍是原型链的语法糖,需注意 super 的使用以及静态方法继承与内置类扩展等规则。
- 【关键点 1】原型链继承实现简单,但实例间共享引用类型属性且无法传参。
- 【关键点 2】构造函数继承可传参且避免共享,但方法无法复用。
- 【关键点 3】组合继承结合两者,是 ES5 中常用的继承方式,但调用两次父类构造函数。
- 【关键点 4】ES6 class 继承通过 extends 实现,本质仍是基于原型的继承。
- 【易错点 1】将原型链继承用于所有场景时,忽略引用类型属性共享带来的隐患。
- 【易错点 2】组合继承中未处理子类原型的 constructor 指向,导致实例的 constructor 指向错误。
- 【易错点 3】ES6 继承中忘记调用 super() 或在调用 super 前使用 this,会抛出语法错误。