继承
继承是通过原型链实现的,实例使用原型的属性和方法属于一种继承
原型和继承的关系
- instanceof 如果原型链出现过这个构造函数,则返回true
- isPrototypeOf 原型方法,判断原型是否包含这个实例
继承方式
- 原型继承
缺点:
- 原型上的引用方法会在实例中共享
- 子构造函数的实例不能给父构造函数函数传参
function Super() { this.name = '11' this.city =['beijing','shanghai'] } function Son() { this.age='12' } Son.prototype = new Super() const shili = new Son() shili.city.push('guangzhou') // ahili1没法给Super传递参数 const shili1 = new Son() // 下面打印是实例间共享 console.log(shili1.city) //[ 'beijing', 'shanghai', 'guangzhou' ] -
盗用构造函数继承: 缺点: 盗用构造函数和构造函数模式一样,每次调用父构造函数都会创建新的属性 优点: 解决了原型继承的缺点,可以传参,实例之间引用类型不会共享
function Super(name) { this.name = '11' this.city =['beijing',name] } function Son(name) { Super.call(this,name) this.age='12' } const shili = new Son('shanghai') shili.city.push('guangzhou') const shili1 = new Son('chengdu') console.log(shili.city) // [ 'beijing', 'shanghai', 'guangzhou' ] console.log(shili1.city) //[ 'beijing', 'chengdu' ] -
组合继承 组合继承就是原型继承和盗用构造函数的组合使用 优点: 1.解决了盗用构造函数的原型函数的缺点,实例间可以共享的,放在父构造函数的原型上,需要传递参数的,放在父构造函数的函数体里 缺点: 父构造函数在子构造函数体调用一次,创建属性在子构造函数的实例上,子构造函数的原型prototype 赋值父构造函数的实例也会创建父构造函数的属性到原型上。实例上的属性会覆盖构造函数原型上的属性
function Super(name) { this.name = '11' this.city =['beijing',name] } Super.prototype.sayHi= function() { console.log('super') } function Son(name) { Super.call(this,name) this.age='12' } Son.prototype = new Super('chengdu') console.log(Son.prototype.city) //[ 'beijing', 'chengdu' ] Son.prototype.sayHolle = function(){ console.log('son') } const shili = new Son('shanghai') console.log(shili.city) //[ 'beijing', 'shanghai' ] -
原型式继承 临时创建一个构造函数,把构造函数的prototype赋值,并返回这个构造函数的实例 优点: 适用于在一个对象的基础上新建另一个对象 缺点: 类似原型继承,实例共享原型上的引用类型
function object(o) { function F() {} F.prototype = o F.prototype.constructor = F return new F() }Object.create: Object.create(原型对象,新实例初始化的一些值集合) 原型式继承在es6通过Object.create实现了,当Object.create不传第二个参数,和原型式继承一摸一样
function object(o) { function F() {} F.prototype = o F.prototype.constructor = F return new F() } const shili = object({name:'11111'}) Object.defineProperties(shili,{age:{value:'18',enumerable:true,writable:true,configurable:true}}) // 上面的代码等价于 Object.create({name:'11111'},{age:{value:'18',enumerable:true,writable:true,configurable:true}}) -
寄生式继承 原理是创建一个实例对象,然后强化它
function object(o) { function F() {} F.prototype = o F.prototype.constructor = F return new F() } function jisheng(prop) { const shili = object(prop) // 不一定非要原声式继承 shili.sayHi = ()=>{ console.log('jishneg') } return shili } const shili = jisheng({}) - 寄生式组合继承 使用盗用构造函数创建父构造函数上的属性,父构造函数原型对象上的属性通过子构造函数原型创建 这样避免了子构造函数原型上不必要的属性创建,所以效率更高 且原型链保持不变
function object(o) {
function F() {}
F.prototype = o
F.prototype.constructor = F
return new F()
}
function jsheng(superFun, sonFun) {
const prototype = object(superFun.prototype)
prototype.constructor = sonFun
sonFun.prototype = prototype
}
function Super(name) {
this.name = '11'
this.city = ['beijing', name]
}
Super.prototype.sayHi = function() {
console.log('super')
}
function Son(name) {
Super.call(this, name)
this.age = '12'
}
jsheng(Super, Son)
const shile = new Son('shanghai')
shile.sayHi() // super