解决缺点一(构造函数继承)
某实例改变父构造函数中引用类型属性的值,所有实例共享修改后的引用类型的属性值
function Parent() { this.arr = [1, 2, 3]; } Parent.prototype.start = function () { } function Children() { Parent.apply(this) //相当于执行了 this.arr = [1, 2, 3]; let p1 = new Children() let p2 = new Children() p1.arr.pop() console.log(p1.arr)//[2,3] console.log(p2.arr)//[1,2,3]
解决缺点二(构造函数继承)
生成实例时不能传参的问题
function Parent(color,name) { this.color = color; this.name = name; this.arr = [1, 2, 3]; this.eat = function () { console.log('走这里了吗') } } Parent.prototype.start = function () { // console.log(this.name,'prototype') } function Children() { console.log(arguments,'arguments') //call传参为多个数值 //apply传值为数组 // Parent.apply(this,arguments) Parent.call(this,...arguments) } let p1 = new Children() let p2 = new Children('red','zhangsan') console.log(p2.color)//red console.log(p2.name)//zhangsan console.log(p1.eat===p2.eat)//false
再次出现的问题
我们每次生成实例的时候都会重新生成构造函数的属性和方法
function Children() { //call传参为多个数值 //apply传值为数组 // Parent.apply(this,arguments) Parent.call(this,...arguments) }
解决重新生成实例时生成构造函数的属性和方法(组合继承:原型链继承+构造函数继承)
- 原型链继承:
- 实例改变引用类型的属性,所有实例共享
- 不能传参。
- 构造函数继承:
- 解决了以上原型链的两个问题
- 但是又出现了新的问题,每次生成实例都会重新生成一份构造函数的属性和方法
function Parent(color,name) { this.color = color; this.name = name; this.arr = [1, 2, 3]; this.eat = function () { console.log('走这里了吗') } } Parent.prototype.start = function () { console.log(this.name,'prototype') } function Children() { console.log(arguments,'arguments') //call传参为多个数值 //apply传值为数组 // Parent.apply(this,arguments) // Parent.call(this,...arguments) // Parent.apply(this,Array.prototype.slice.call(arguments, 1)) Parent.apply(this,[].slice.call(arguments, 1)) } Children.prototype = new Parent(); Children.prototype.constructor = Children let p1 = new Children(1,'red','zhangsan') let p2 = new Children(2,'red','zhangsan') console.log(p1.eat()) console.log(p2.eat()) console.log(p1.start===p2.start) //true
解决了三个痛点:
- 不可传参数
- 多占内存
- 改变引用类型属性,所有实例共享
寄生组合继承(再次出现问题,构造函数调用两次)
1. Parent.call(this,...arguments) ... 2.Children.prototype = new Parent();