从零开始学_JavaScript_系列(42)——简述js的八种继承方式

来源:互联网 发布:兴业银行淘宝网银支付 编辑:程序博客网 时间:2024/06/05 12:41

继承方式有以下八种:

  1. prototype:传统原型链继承,要继承的函数的prototype属性,被被继承函数的实例所替代;
  2. apply、call继承:在要继承的函数里,调用被继承的函数,并利用apply和call传参this实现;
  3. Object.assign() 属性合并继承(非原型链),类似2,可以同时合并多个;
  4. Object.create() 以某个对象为原型创建属性继承(原型链继承),类似1,可以设置enumberable等属性;
  5. 组合继承:apply或call继承属性,prototype继承函数(主要是让函数复用,多个实例指向同一个函数方法,而不是每个实例都有一个函数方法);
  6. 原型式继承:使用继承的函数Father,创建一个新实例let father = new Father(),创建一个空函数Fun,将father作为空函数Fun的原型链,然后用空函数Fun创建一个新的实例let f = new Fun(){},将其他要继承的属性,依次添加到f这个对象上,形成继承。
  7. 寄生式继承:类似上面,声明一个Test函数,参数是被继承的函数的实例。这个函数里做了什么事情呢?首先在这个实例上用6的方式将这个实例添加到Fun的原型链上,然后再在Fun的实例f上添加各种属性,最后将f返回。相当于做了一个封装,无论丢什么对象,都会添加同样的属性和方法。
  8. 组合寄生继承:(下面细说)


上面8种方式里,其中1,2,5,6,7,8可以参考这个链接重新理解JS的6种继承方式,而3是es6的新增方法,4是es5的新增方法。

寄生组合继承:

  1. 简单来说,我把属性放在Father函数中,把方法放在Father函数的prototype上;
  2. 然后我创建一个空的函数Fun,让Father的prototype成为这个空函数的原型链(prototype);
  3. 此时,就相当于这个Fun拥有了被继承的函数的方法;
  4. 然后再var fun = new Fun(),那么这个实例自然也有Father的方法;
  5. 此时,fun的属性为:一个空对象,他的__proto__属性里有fun1和fun2方法(原因参照上面的7.1和7.2);
  6. 我们再让fun的constructor属性(构造函数属性)指向Father;
  7. 于是我们有了一个这样的对象:
    拥有一个constructor属性,指向Father;
    原型链上有Father的prototype方法;
  8. 有没有发现,这个和函数的prototype属性的构成很像;
  9. 于是将这个对象作为Child的prototype。
  10. 此时Child的原型链上有了从Father继承来的方法;
  11. 在Child里,以call或者apply的方式调用Father函数,于是Child继承了Father的属性;
  12. 此时Child既继承了Father的属性(call或apply),又继承了Father的方法(prototype),而因为方法在原型链上,因此Child的实例都共用同一个Father的方法。
阅读全文
0 0