JS的继承(6种)

张开发
2026/6/9 13:19:49 15 分钟阅读
JS的继承(6种)
JS是基于原型prototype的继承不是类继承。所有继承本质让子类型的原型指向父类型的实例。一、原型链继承最基础原理子构造函数的prototype父构造函数的实例。function Parent() { this.name parent; this.colors [red, blue]; } function Child() {} // 核心子原型 父实例 Child.prototype new Parent(); const c1 new Child(); console.log(c1.name); // parent缺点1.引用类型属性被所有实例共享一个改全改2.创建child时不能向parent传参二、借用构造函数继承call/apply原理在子构造函数里call父构造函数复制一份属性function Parent(name) { this.name name; this.colors [red, blue]; } function Child(name) { // 借用父构造继承属性还能传参 Parent.call(this, name); } const c1 new Child(小明); c1.colors.push(green); console.log(c1) const c2 new Child(小红); console.log(c2) // c2.colors 不受影响解决了引用共享问题优点:可传参缺点方法都写在构造函数里每次创建实例都重复生成无法复用浪费内存三、组合继承原理原型链继承方法复用借用构造函数继承属性不共享function Parent(name) { this.name name; this.colors [red]; } Parent.prototype.say function () { console.log(this.name) }; function Child(name, age) { // 继承属性第1次调用 Parent Parent.call(this, name); this.age age; } // 继承方法第2次调用 Parent Child.prototype new Parent(); Child.prototype.constructor Child; // 修复构造器指向 const c1 new Child(张三,18) console.log(c1);优点1.属性不共享2.方法复用3.可传参缺点父构造函数被调用了2次四、原型式继承原理基于一个现有对象创建新对象不使用构造函数。cosnt parent {name:parent}; const child Object.create(parent)缺点1.依然共享引用类型2.无法传参、无法复用方法五、寄生式继承原理封装一个函数在内部创建对象并且给这个新对象加方法、加属性返回对象通俗理解就是我不写构造函数我基于一个已有的对象去生出一个新对象新对象继承父对象的所有东西我再额外给新对象加一点独有的功能然后把整个过程封装成函数方便后续批量创建。// 1. 被继承的父对象 const person { name: 父对象, sayHello: function () { console.log(hello); } }; // 2. 寄生式继承核心函数 function createSon(original) { // 第一步创建新对象继承 original寄生 const son Object.create(original); // 第二步给新对象【增强】——加自己的方法/属性 son.age 18; // 加属性 son.sayAge function () { // 加方法 console.log(this.age); }; // 第三步返回这个增强后的对象 return son; } // 3. 使用 const son1 createSon(person); // son1 继承了 person 的 sayHello // 又拥有了自己的 age、sayAge缺点方法无法复用每次都创建新方法。六、寄生组合式继承原理解决组合继承调用两次父构造函数的问题用借用构造函数继承属性、用原型式继承父原型不new Parentfunction Parent(name) { this.name name; } Parent.prototype.say function(){}; function Child(name, age) { Parent.call(this, name); // 继承属性只调用1次 this.age age; } // 核心继承父原型不调用父构造 Child.prototype Object.create(Parent.prototype); Child.prototype.constructor Child;优点1.只调用一次父构造2.属性不共享3.方法复用4.性能最好七、ES6 class extends语法糖原理本质就是寄生组合式继承只是写法更像类class Parent { constructor(name) { this.name name; } say() {} } class Child extends Parent { constructor(name, age) { super(name); // 等于 Parent.call(this,name) this.age age; } }注意1.super必须在this之前调用2.底层还是原型继承不是真正的类继承总结JS 本质是基于原型的继承不是传统的类继承核心靠原型链实现。1.最基础的是原型链继承让子构造函数的 prototype 指向父实例。但缺点很明显引用类型属性会被所有实例共享而且创建子类时不能给父类传参。2.后来出现借用构造函数继承用 call/apply 在子类里调用父构造可以传参、解决引用共享问题但方法不能复用每个实例都创建一遍方法浪费内存。3.所以又有组合继承用原型链继承方法借用构造函数继承属性。但它有个问题父构造函数会被调用两次有性能浪费。4.最优方案是寄生组合式继承用 Object.create(Parent.prototype) 继承父原型不再 new Parent()只通过 call 继承属性。只调用一次父构造完美解决所有问题这是 ES6 之前最标准、最推荐的继承方式。5.ES6 的 class extends 其实就是语法糖底层实现完全就是寄生组合式继承本质还是原型链不是真正的类继承。

更多文章