3、JavaScript 继承详解
目录一、继承的原理1. 原型链机制二、实现方式1. 原型链继承2. 构造函数继承借用构造函数3. 组合继承最常用4. 原型式继承5. 寄生式继承6. 寄生组合继承最优方案7. ES6 Class 继承推荐三、面试如何回答才精彩 回答框架第一层原理认知第二层演进历程第三层最佳实践第四层对比说明第五层延伸知识 加分项一、继承的原理1. 原型链机制JavaScript 继承的核心是原型链Prototype Chain每个对象都有一个内部属性[[Prototype]]通过__proto__访问当访问对象属性时如果对象本身没有会沿着原型链向上查找原型链的顶端是Object.prototype再向上是nullfunction Parent() {} Parent.prototype.getName function() { return parent; } const child new Parent(); // child.__proto__ Parent.prototype // Parent.prototype.__proto__ Object.prototype二、实现方式1.原型链继承function Parent() { this.name parent; this.colors [red, blue]; } Parent.prototype.getName function() { return this.name; } function Child() {} Child.prototype new Parent(); // 缺点 // - 引用类型属性被所有实例共享 // - 无法向父类构造函数传参2.构造函数继承借用构造函数function Parent(name) { this.name name; this.colors [red, blue]; } function Child(name) { Parent.call(this, name); // 借用父类构造函数 } // 优点避免引用类型共享、可传参 // 缺点方法都在构造函数中定义无法复用3.组合继承最常用function Parent(name) { this.name name; this.colors [red, blue]; } Parent.prototype.getName function() { return this.name; } function Child(name, age) { Parent.call(this, name); // 第二次调用Parent this.age age; } Child.prototype new Parent(); // 第一次调用Parent Child.prototype.constructor Child; // 优点结合前两者优点 // 缺点调用两次父类构造函数4.原型式继承function object(o) { function F() {} F.prototype o; return new F(); } // 等同于 ES5 的 Object.create() // 缺点引用类型属性共享5.寄生式继承function createObj(o) { const clone Object.create(o); clone.sayHi function() { console.log(hi); } return clone; } // 缺点方法无法复用6.寄生组合继承最优方案function Parent(name) { this.name name; this.colors [red, blue]; } Parent.prototype.getName function() { return this.name; } function Child(name, age) { Parent.call(this, name); this.age age; } // 核心不调用Parent构造函数来设置子类原型 Child.prototype Object.create(Parent.prototype); Child.prototype.constructor Child; // 优点只调用一次父类构造函数效率高7.ES6 Class 继承推荐class Parent { constructor(name) { this.name name; } getName() { return this.name; } } class Child extends Parent { constructor(name, age) { super(name); // 必须先调用super this.age age; } } // 本质寄生组合继承的语法糖三、面试如何回答才精彩回答框架第一层原理认知JavaScript 继承基于原型链机制。当访问对象属性时如果自身没有会沿着__proto__链向上查找直到Object.prototype。第二层演进历程继承方式经历了演进原型链继承引用类型共享问题构造函数继承无法继承原型方法组合继承调用两次构造函数寄生组合继承目前最优的 ES5 方案ES6 Class语法糖本质仍是寄生组合继承第三层最佳实践// 展示寄生组合继承的核心代码 function inheritPrototype(child, parent) { const prototype Object.create(parent.prototype); prototype.constructor child; child.prototype prototype; } function Parent(name) { this.name name; } Parent.prototype.sayName function() { console.log(this.name); } function Child(name, age) { Parent.call(this, name); // 继承属性 this.age age; } inheritPrototype(Child, Parent); // 继承方法第四层对比说明方式优点缺点原型链简单直观引用类型共享、无法传参构造函数避免共享、可传参方法无法复用组合继承常用、功能完整调用两次构造函数寄生组合最优解实现复杂ES6 Class语法清晰需要转译支持第五层延伸知识instanceof 原理检查对象原型链上是否存在构造函数的 prototypeES6 extends 与 ES5 的区别ES6 子类必须在 constructor 中调用 superES5 是先创建子类实例再添加父类属性ES6 是先创建父类实例再用子类构造函数修改加分项能手写寄生组合继承理解__proto__与prototype的区别知道 Class 的本质是函数了解继承在实际项目中的应用场景总结现代开发优先使用 ES6 Class但理解底层原理寄生组合继承是核心竞争力