不得不说红宝书第六章真的很重要,也真的很难QAQ
原型链继承
原型链继承function Pet(){
this.master = "zxz"
}
Pet.prototype.about = function(){
console.log(`这只宠物的主人是${this.master}`)
}
function Cat(color){
this.color = color
}
Cat.prototype = new Pet()
Cat.prototype.constructor = Cat
var coco = new Cat()
coco.about() //这只宠物的主人是zxz
构造函数继承
构造函数继承function Pet(name,age){
this.name = name
this.age = age
}
function Cat(name,age,color){
this.color = color
Pet.call(this,name,age)
}
var coco = new Cat("coco",3,"白")
console.log(coco) //Cat { color: '白', name: 'coco', age: 3 }
组合继承
组合继承- 通过call或者apply,继承父类构造函数中的属性
- 如果不写的话,还是可以通过原型链获得属性;但是对于需要向构造函数传入参数的属性,因为没法传参,值只能undefined
- 替换原型,子类的原型对象设置为父类的一个实例
- 保持构造函数的一致性
- 第一步是基于构造函数的继承,第二步是基于原型链的继承,两者组合使用
- 规避只使用原型链继承时 引用类型 原型属性被所有实例共享的问题
- 规避只使用构造函数继承时 实例的方法没有复用 的问题
function Pet(name,age){
this.name = name
this.age = age
}
Pet.prototype.about = function(){
console.log(`这只宠物叫${this.name},今年${this.age}岁了`)
}
function Cat(name,age,color){
this.color = color
Pet.call(this,name,age) //通过call或者apply定义Pet中以及定义的属性
}
Cat.prototype = new Pet() //继承原型,coco.__proto__ => Cat.prototype ; coco.__proto__.__proto__ => new Pet().__proto__ => Pet.prototype
Cat.prototype.constructor = Cat // 保持构造函数的一致性,不然构造函数指向Pet的
Cat.prototype.about = function(){ //重写对象方法
console.log(`这只${this.color}色猫猫叫${this.name},今年${this.age}岁了`)
}
var wowo = new Pet("wowo",4)
wowo.about()//这只宠物叫wowo,今年4岁了
var coco = new Cat("coco",3,"白")
coco.about()//这只白色猫猫叫coco,今年3岁了
console.log(coco.__proto__.constructor) //[Function: Cat]
console.log(coco instanceof Cat) //true
console.log(coco instanceof Pet) //true
缺点:原型上有一些多余的属性
console.log(coco)
原型式继承
原型式继承function object(o){
function F(){}
F.prototype = o
return new F();
}
ES5使用object.create()规范了原型式继承
(method) ObjectConstructor.create(o: object): any (+1 overload)
有重载,第二个参数格式类似Object.definedProperties()
方法
寄生式继承
寄生式继承function createAnother(original){
var clone = object(original); // object是上面的原型式继承
clone.sayHi = function(){
console.log('hi')
}
return clone
}
寄生组合式继承
寄生组合式继承1.通过call或者apply,继承父类构造函数中的属性
2.使用Object.create(Pet.prototype)替换原型,子类的原型对象设置为父类的一个原型式继承
3.保持构造函数的一致性
好像就是把组合继承中的Cat.prototype = new Pet()
换成了Cat.prototype = Object.create(Pet.prototype)
避免了二次调用new SuperType()
function Pet(name, age) {
this.name = name
this.age = age
}
Pet.prototype.about = function () {
console.log(`这只宠物叫${this.name},今年${this.age}岁了`)
}
function Cat(name, age, color) {
this.color = color
Pet.call(this, name, age) //通过call或者apply定义Pet中以及定义的属性
}
/***** 继承步骤上组合继承不同的地方 ***********************/
Cat.prototype = Object.create(Pet.prototype)
/***** **************************************************/
Cat.prototype.constructor = Cat // 保持构造函数的一致性,不然构造函数指向Pet的
Cat.prototype.about = function () { //重写对象方法
console.log(`这只${this.color}色猫猫叫${this.name},今年${this.age}岁了`)
}
var coco = new Cat("coco", 3, "白")
/***** 这部分得到的结果都和组合继承相同 *******************/
var wowo = new Pet("wowo", 4)
wowo.about() //这只宠物叫wowo,今年4岁了
var coco = new Cat("coco", 3, "白")
coco.about() //这只白色猫猫叫coco,今年3岁了
console.log(coco.__proto__.constructor) //[Function: Cat]
console.log(coco instanceof Cat) //true
console.log(coco instanceof Pet) //true
/***** **************************************************/
console.log(coco)
相比于组合继承,在Pet原型上少了很多多余的属性
ES6中的继承
ES6中的继承class
实现继承的核心在于使用 extends
表明继承自哪个父类,并且在子类构造函数中必须调用 super
,因为这段代码可以看成 Pet.call(this, name, age)
。
class Pet {
constructor(name, age) {
this.name = name
this.age = age
}
about() {
console.log(`这只宠物叫${this.name},今年${this.age}岁了`)
}
}
class Cat extends Pet {
constructor(name, age, color) {
super(name, age)
this.color = color
}
about() { //重写对象方法
console.log(`这只${this.color}色猫猫叫${this.name},今年${this.age}岁了`)
}
}
/***** 这部分得到的结果都和组合继承相同 *******************/
var wowo = new Pet("wowo", 4)
wowo.about() //这只宠物叫wowo,今年4岁了
var coco = new Cat("coco", 3, "白")
coco.about() //这只白色猫猫叫coco,今年3岁了
console.log(coco.__proto__.constructor === Cat) //[Function: Cat]
console.log(coco instanceof Cat) //true
console.log(coco instanceof Pet) //true
/***** **************************************************/
console.log(coco)
[外链图片转存失败(img-uFRHVZH1-1566549271996)(https://user-images.githubusercontent.com/44082279/61199826-e92f8900-a711-11e9-897c-def87f5f45c3.png)]
另外,类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
Object.keys(Pet.prototype) //[]