【js基础】继承(原型链继承、组合式继承、寄生组合式继承、class的实现)
1、原型链继承缺点1父类引用类型属性会被子类所有实例共享改一个全变2子类不能给父类传参// 原型链继承 function Parent() { this.name parent this.arr [1,2,3] // 引用类型坑点 } function Child(){} Child.prototype new Parent(); let c1 new Child(); let c2 new Child(); c1.arr.push(4); console.log(c1.arr, c2.arr)2、构造函数继承缺点1方法在构造函数中每个实例都会创建一遍无法复用2原型上的属性、方法不能继承function Parent(name) { this.name name; this.arr [1,2,3] // 引用类型坑点 } function Child(name){ Parent.call(this, name) } let c1 new Child(宏宏); let c2 new Child(兰兰) console.log(c1.name) c1.arr.push(4); console.log(c1.arr, c2.arr)3、组合继承结合上面两种缺点12次调用父类构造函数、有性能问题2子类原型上的属性是冗余的实例在构造函数中已经创建了自己的属性function Parent(name) { this.name name; this.arr [1,2,3] // 引用类型坑点 } Parent.prototype.say function() { console.log(say hi) } function Child(){ Parent.call(this) } Child.prototype new Parent(); let c1 new Child(宏宏); let c2 new Child(兰兰)4、原型继承缺点和原型链继承一样const person { name: 张三, colors: [红, 绿, 蓝], // 引用类型坑点 say() { console.log(this.name); } }; // 2. 使用原型式继承创建新对象 const p1 Object.create(person); p1.say()5、寄生继承寄生继承 在原型继承基础上增添一些方法6、组合寄生式继承function Parent() { this.name parent } Parent.prototype.say function() {} function Child() { Parent.call(this) // 1次 } // 核心继承父类原型不调用父构造函数 Child.prototype Object.create(Parent.prototype) Child.prototype.constructor Child // 修复指向7、class继承实际就是组合寄生的语法糖class Parent {} class Child extends Parent { constructor() { super() // 相当于 Parent.call(this) } }8、常见面试问答1说说js继承的理解答js继承是基于原型链的继承而不是基于类的继承。每个实例都有_proto_属性每个构造函数都有prototype每个实例的_proto_指针指向构造函数的原型查找属性、方法时会向上查找直到找到null。结合原型链概念来说2为什么不能直接用Child.prototype Parent.prototype答因为原型是引用类型直接赋值会污染父类所有实例都会有影响。3Object.create()的作用是什么答创建一个空对象使七_proto_属性指向传入的参数。4继承中constructor为什么要修正答不修正构造函数是Parent5Object.create (null) 和 {} 有什么区别继承关系有什么不同答{}的_proto_指向Object.prototype,有Object的方法在上面null的_proto_属性是undefined没有原型链。6如何实现一个 “继承”既能继承属性又不污染原型function inherit(child, parent) { let prototype Object.create(parent.prototype); prototype.constructor child; child.prototype prototype; }7用代码还原 ES6 继承底层// 父类 function Parent(name) { this.name name; } Parent.prototype.say function () {} // 子类 function Child(name, age) { // 3. 调用父类创建 this Parent.call(this, name); this.age age; } // 1. 子类 __proto__ 指向父类继承静态属性 Child.__proto__ Parent; // 2. 子类原型继承父类原型 Child.prototype Object.create(Parent.prototype); Child.prototype.constructor Child;