pma934 / pma934.github.io

build by https://github.com/pma934/vuetify-blog
2 stars 0 forks source link

js继承 #16

Open pma934 opened 5 years ago

pma934 commented 5 years ago

不得不说红宝书第六章真的很重要,也真的很难QAQ

原型链继承

原型链继承 ```javascript 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 ```

构造函数继承

构造函数继承 ```javascript 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 } ```

组合继承

组合继承 1. 通过call或者apply,继承父类构造函数中的属性 - 如果不写的话,还是可以通过原型链获得属性;但是对于需要向构造函数传入参数的属性,因为没法传参,值只能undefined 2. 替换原型,子类的原型对象设置为父类的一个实例 3. 保持构造函数的一致性 - 第一步是基于构造函数的继承,第二步是基于原型链的继承,两者组合使用 - 规避**只使用原型链继承时 引用类型 原型属性被所有实例共享的问题** - 规避**只使用构造函数继承时 实例的方法没有复用 的问题** ```javascript 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 ``` 缺点:原型上有一些多余的属性 ```javascript console.log(coco) ``` ![image](https://user-images.githubusercontent.com/44082279/61166551-12111c00-a562-11e9-844c-c489485b3e77.png)

原型式继承

  1. 创造一个新的空的类
  2. 新的类的原型指向要继承的类
  3. 返回一个新的类的实例
原型式继承 ```javascript function object(o){ function F(){} F.prototype = o return new F(); } ``` ES5使用object.create()规范了原型式继承 `(method) ObjectConstructor.create(o: object): any (+1 overload)` 有重载,第二个参数格式类似`Object.definedProperties()`方法

寄生式继承

寄生式继承 ```javascript 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() ```javascript 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 /***** **************************************************/ ``` ```javascript console.log(coco) ``` ![image](https://user-images.githubusercontent.com/44082279/61166546-f60d7a80-a561-11e9-803a-874a72a48f51.png) 相比于组合继承,在Pet原型上少了很多多余的属性

ES6中的继承

ES6中的继承 `class` 实现继承的核心在于使用 `extends` 表明继承自哪个父类,并且在子类构造函数中必须调用 `super`,因为这段代码可以看成 `Pet.call(this, name, age) `。 ```javascript 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 /***** **************************************************/ ``` ```javascript console.log(coco) ``` ![image](https://user-images.githubusercontent.com/44082279/61199826-e92f8900-a711-11e9-897c-def87f5f45c3.png) 另外,类的内部所有定义的方法,都是不可枚举的(non-enumerable)。 ```javascript Object.keys(Pet.prototype) //[] ```