这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
构造函数+原型链方式组合继承
! 继承方式3:
- 构造函数方式+原型链方式 组合继承
- 通过parent.call(this)改变上下文this指向,父类构造函数上的属性和方法设置到子类上,相互独立避免影响,通过child.prototype = new parent()
- 实现继承父类原型对象上的属性和方法
- 缺点:这种方式实现继承,父类构造函数会执行两次分别在parent.call和child.prototype=new parent(),而且父类构造函数的属性和方法会在子类和子类原型上
- 都存在,执行delete c.arr 指删除了子类对象自身的arr属性,对象的原型上仍然可以找到,访问c.arr通过原型链查找机制仍然可以访问到
function Child3(sex,name,age){
this.c_sex = sex;
Parent.call(this,name,age)
}
Child3.prototype = new Parent()
var c3 = new Child3("man","tom",22)
console.log(c3)
构造函数方式+原型链方式组合继承(优化)
- 构造函数方式+原型链方式组合继承(优化),解决了上面3方式的问题
- (注:以前child.prototype = new parent()方式是为了获得parent构造函数上的属性和方式
现在child.prototype = parent.prototype 只获得原型上属性和方法,用parent.call(this)获得构造函数上的属性和方法)- 缺点:无法区分c到底是由Child直接实例化的还是Parent直接实例化的。用instanceof关键字来判断是否是某个对象的实例就基本无效了。 c.constructor.name =="parent"
function child4(name,age,sex) {
Parent.call(this,age,sex)
this.c_name = name
}
child4.prototype = Parent.prototype
let c4 = new child4("c4",99,"girl")
Object.create方式实现继承
- Object.create方式实现继承, child5.prototype = Object.create(parent.prototype)//child.prototype.proto=parent.prototype,通过create创建的child.prototype这个新对象的 proto===parent的原型对象,所以就继承了parent原型上的属性和方法,重新指定了constructor为child,相当于在中间加了一层,console.dir(c5)看一下 child5.prototype.constructor = child5 ! let newObj = Object.create(old) 方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__,就相当于:newObj.proto = old
function child5(name,age,sex) {
Parent.call(this,age,sex)
this.name = name
}
function child55(name,age,sex) {
Parent.call(this,age,sex)
this.name = name
}
child55.prototype = Object.create(parent.prototype)
child55.prototype.constructor = child55
//! 这里不用Object.create ,直接是上面继承方式4 的继承上指定constructor ,这样为什么不如这个好呢,因为子类的原型对象的属性和从父类那里集成的原型对象属性混在一起了,从数据结构上也不如Object.create的方式好
child5.prototype = parent.prototype
child5.prototype.constructor = child5
child5.prototype.cpro = "dsd"
child55.prototype.cpro = "dsd"
console.log(c5,c55)