Js继承
要想继承,就必选有一个要被继承的产业
function who(name){
this.name = name
this.say = function(){
console.log(this.name)
}
}
who.prototype.age = 10
第一种方法:原型链继承
function xiaoming(){
this.name = 'xiaoming'
}
xiaoming.prototype = new who()
let xiaoming1 = new xiaoming()
console.log(xiaoming1) //who()
console.log(xiaoming1.name) //xiaoming
console.log(xiaoming1.age) //10
console.log(xiaoming1 instanceof who) //true
重点:让新实例的原型等于父级的实例xiaoming.prototype = new who()
优点:
- 可继承父级构造函数属性
- 可继承父级原型的属性
缺点:
- 新实例无法像父级构造函数传参
- 所有的新实例都会共享父级构造函数的属性,一个新实例改变了父级构造函数属性的值,那么其他的新实例也会跟着改变
第二种方法:构造函数继承
function xiaohong(){
who.call(this,"xiaohong")
}
let xiaohong1 = new xiaohong()
console.log(xiaohong1) //who()
console.log(xiaohong1.name) //xiaohong
console.log(xiaohong1.age) //undefined
console.log(xiaohong1 instanceof who) //false
重点:使用call()
和apply()
的方法将父类函数继承过来
优点:
- 可以像父级函数传参
- 解决了父级函数属性共享的问题
- 可以用
call()
和apply()
继承多个
缺点:
- 只能继承父级构造函数的属性,无法继承父级构造函数原型上的属性
- 无法实现构造函数的复用,每次用每次都得继承
第三种方法:组合继承(常用)
function xiaopeng(name){
who.call(this,name)
}
xiaopeng.prototype = new who()
let xiaopeng1 = new xiaopeng('xiaopeng')
console.log(xiaopeng1.name) //xiaopeng
console.log(xiaopeng1.age) //10
console.log(xiaopeng1 instanceof who) //true
重点:使用了原型继承和构造函数继承
优点:
- 可以继承父级原型上的属性
- 可以传参也可以复用
- 每个实例继承到的构造函数都是私有的
缺点:
- 消耗内存:调用两次父级构造函数
第四种方法:原型式继承
function color(obj){
function fn(){}
fn.prototype = obj
return new fn
}
let red = new who()
let red1 = color(red)
red1.name = 'red'
console.log(red1.name) //red
console.log(red1.age) //10
console.log(red1 instanceof who) //true
重点:先封装一个函数,用来返回这个函数的调用,那么这个函数就变成一个可以随意添加属性的实例或对象
优点:类似于复制一个对象
缺点:所有的实例都会继承构造函数原型上的属性
第五种方法:寄生式继承
function color(obj){
function fn(){}
fn.prototype = obj
return new fn
}
let red = new who()
//以上是原型式继承
function colorObject(obj){
let col = color(obj)
col.name = 'green'
return col
}
let red1 = colorObject(red)
console.log(red1.name) //green
console.log(red1.age) //10
console.log(red instanceof who) //true
console.log(typeof colorObject) //function
console.log(typeof red1) //object
重点:就是在原型式的外面再包一个函数体
优点:没有创建自定义类型,这个函数顺理成章就成了创建的新对象
缺点:跟借用构造函数模式一样,每次创建对象都会创建一遍方法
第六种方法:组合寄生继承(常用)
function color(obj){
function fn(){}
fn.prototype = obj
return new fn
}
let red = color(who.prototype)
function blue(){
who.call(this)
}
blue.prototype = red
red.constructor = blue
let blue1 = new blue()
console.log(blue1.age) //10
重点:使用寄生继承和组合继承的方法
优点:
- 只调用一次父级构造函数
- 原型链保持不变