一、原型链继承
将父类的实例作为子类的原型
javascript
function Father(){
this.name = 'Tony'
}
function Son() {}
Son.prototype = new Father()
let son = new Son();
console.log(son.name) // Tony
缺点:
- 父类所有的引用类型属性都会被所有子类共享,一个子类修改了属性值就会影响到其他子类。
- 子类不能给父类的构造函数传参
二、构造函数继承
在子类构造函数中调用父类构造函数并通过call或apply给父类传参、修改this指向。
javascript
function Father(name){
this.info = {
name:name,
job:'teacher'
}
this.sayName(){
console.log(this.info.name)
}
}
function Son (name){
Father.call(this,name)
}
let s = new Son('Jerry');
let s2 = new Son ('Mike');
console.log(s.info.name) //Jerry
console.log(s2.info.name) // Mike
通过使用call()
或apply()
方法,Parent
构造函数在为Child
的实例创建的新对象的上下文执行了,就相当于新的Child
实例对象上运行了Parent()
函数中的所有初始化代码,结果就是每个实例都有自己的info
属性。
优点:
- 可以给父类传参
- 父类的引用类型不会被子类共享
缺点:
- 子类不能访问父类原型上定义的方法(prototype上挂在的方法)
三、组合式继承
组合式继承综合了原型链继承和构造方法继承的优点,通过原型链继承获得父类原型对象上的属性和方法。通过引用父类构造方法达到隔离子类共享属性,给父类传递参数 。
javascript
function Father (name) {
this.name=name
}
Father.prototype.sayName=function(){
console.log(this.name)
}
function Son (name) {
Father.call(this,name)
}
Son.prototype = new Father()
//手动挂载构造起,指向自己的构造方法
Son.prototype.constructor = Son
let s1 = new Son('Mike')
s1.sayName() // Mike
let s2 = new Son('Jerry')
s2.sayName() //Jerry
优点:
- 父类的方法可以复用
- 子类可以向父类传参
- 父类构造函数中的引用类型数据不会被共享
四、原型继承
对参数对象的一种浅复制 ,当Object.create()只有一个参数时与下面代码中的Object()方法相同
javascript
let student = {
hobbies:['music','football','basketball']
}
function Object (o) {
function F(){}
F.prototype=o
return new F()
}
let s1 = Object(student)
s1.hobbies.push('sing')
console.log(s1.hobbies) //['music', 'football', 'basketball', 'sing']
let s2 = Object(student)
s2.hobbies.push('dance')
console.log(s2.hobbies) //['music', 'football', 'basketball', 'sing','dance']
优点:
- 父类方法可复用
缺点:
- 父类的引用会被子类共享
- 子类不能向父类传参
五、寄生试继承
寄生式继承是在原型继承基础上的拓展,类似于一个工厂模式,即创建一个用于封装继承的函数,该函数内部对参数对象做了增强。
javascript
function Object (person){
function F () {}
F.prototype = person;
return new F()
}
function createObject(person){
let obj = Object(person)
obj.sayHello = function(){
console.log('hello')
}
return obj
}
let person = {
name:'tony',
age:32
}
let p1 = createObject(person)
p1.sayHello() //hello
p1.name //tony
六、寄生式组合继承
组合式继承有看似完美却有一个缺点,那就是父类的构造函数会被执行两次,一次是父类实例化时,一类是子类实例化时。这样就会造成内存没必要的消耗,寄生式组合继承正是弥补了这个短板,时目前最为理想的继承方式。
javascript
function extend(subClass,superClass){
var prototype = object(superClass.prototype);//创建对象
prototype.constructor = subClass;//增强对象
subClass.prototype = prototype;//指定对象
}
七、ES6继承
javascript
class supClass {
constructor(name) {
this.name = name
}
sayName(){
console.log(this.name)
}
}
class subClass extends supClass{
constructor (name) {
super(name)
this.name = name
}
}
let sub = new subClass ('subClass')
console.log(sub.name)
sub.sayName() // subClass