原型链继承
function Parent(){this.name = 'kevin'
}Parent.prototype.getName = function(){console.log(this.name)
}function Child(){}
Child.prototype = new Parent()var child = new Child()
console.log(child.name) //kevin
优点:
- 简单,容易实现
缺点:
- 来自父类原型对象的引用属性是所有子类实例共享的
- 创建子类实例时,无法向父类构造函数传参
借用构造函数(经典继承)
function Parent(name){this.name = name
}function Child(name){Parent.call(this,name)
}let child = new Child('Tom')
let child1 = new Child('Jack')
console.log(child.name) //Tom
console.log(child1.name) //Jack
优点:
- 解决了子类型实例共享父类引用属性的问题
- 创建子类实例时,可以向父类构造函数传参
缺点:
- 无法实现函数复用 ,方法在构造函数中定义,每次创建子类实例都会创建一个新方法,占用内存
组合继承(原型链继承和经典继承的双剑合璧)
function Parent(name){this.name = namethis.color = ['red','bule','green']
}Parent.prototype.getName = function(){console.log(this,name)
}function Child(name,age){this.age = ageParent.call(this,name)
}Child.prototype = new Parent()
Child.prototype.constructor = Child
Child.prototype.getAge = function(){console.log(this.age)
}let child = new Child('Tom',12)
console.log(child.name) //Tom
child.getAge() //12
child.color.push('blcak')
console.log(child.color) //['red','bule','green','black']let child1 = new Child('Jack',18)
console.log(child1.name) //Jack
child1.getAge() //18
console.log(child1.color) //['red','bule','green']
优点:
- 不存在父类引用属性共享问题
- 可以给父类构造函数传参
- 通过原型属性设置方法,使得函数可复用
- 最常用的继承方式
缺点(小瑕疵):
- 子类调用了两次父类构造函数,生成了两个父类实例,第二次调用改变了指向第一个实例的指针,使得第一个实例变得多余了
原型式继承
function object(o){ function F(){}F.prototype = oreturn new F()
}//在ES5中有了新方法代替Object.created(o,{name:'Ton'等新属性})let person = {name:'Tom',color : ['red','bule','green']
}let person1 = Object.create(person)
let person2 = Object.create(person)person1.name = 'Jack'
person1.color.push('black')
person2.name = 'Kevin'
person1.color.push('yellow')console.log(person1.name) //Jack
console.log(person2.name) //Kevin
console.log(person1.color == person2.color) //true
优点:
- 从已有对象衍生新对象,不需要创建自定义类型,更像是对象复制
缺点:
- 原型引用的属性被实例所共享
- 无法实现代码复用
寄生式继承
let person = {name:'Tom',color : ['red','bule','green']
}function createAnother(o){ let clone = create(o)clone.getName(){console.log(this.name)}return clone //clone这个对象不仅有原型引用属性,还有自己的方法
}let person1 = createAnother(person)
person1.getName() //Tom
优点:
- 不需要创建自定义类型
缺点:
- 原型引用的属性被实例所共享
- 无法实现代码复用
##寄生组合式继承(最佳方式)
function Parent (name) {this.name = name;this.colors = ['red', 'blue', 'green'];
}Parent.prototype.getName = function () {console.log(this.name)
}function Child (name, age) {Parent.call(this, name);this.age = age;
}function prototype(Child,Parent){ //获得父类型原型上的方法let prototype = object(Parent.prototype) //创建父类型原型的一个副本,相当于prototype.__proto__ = Parent.prototypeprototype.constructor = ChildChild.prototype = prototype
}prototype(Child,Parent) //必须执行这个函数,才能进行给子类型原型写方法,顺序调转的话子类型原型会被重写
Child.prototype.getName = function(){console.log(this.name)
}
优点:完美 缺点:用起来麻烦
class继承
class Parent {constructor(name,age){this.name = namethis.age = age}showName(){console.log(this.name);}
}class Child extends Parent{constructor(name,age,sex){super(name,age)this.sex = sex}showSex(){console.log(this.sex);}
}
let parent = new Parent('Jack',30)
console.log(parent.name,parent.age);
let child = new Child('Tom',12,'男')
console.log(child.name,child.age);
child.showName() //Tom
child.showSex() //男