js 的继承以及 call && apply

  在 js 中 es6 新增了 class 然后通过 extends 来实现继承的方式,但其原理都是在 es5 的基础上实现的,在 es5 中大致存在这几种继承的方式:

  1、原型继承

    例如 function  dog () {

        this.classType = '犬科';

        this.className = '狗';

      }

      function yellowDog () {

        this.name = '黄狗';

      }

      yellowDog.prototype = new dog();

      此时,dog 就成为了 yellowDog 的原型,yellowDog 也具有了 classType 以及 className 的属性;

  2、构造继承

    构造继承是指在构造函数中去继承

    例如 function dog () { }

      function yellowDog () {

        dog.call(this);

        this.name = '黄狗

      }

      此时,dog 的 classType 等属性并不是作为 yellowDog 原型链的属性,而是成为了 yellowDog 的属性;

  3、实例继承

    例如: function animal () { this.classType = '犬科' }

       function yellowDog () {

         var obj = new animal()

         obj.name = '黄狗'

         return obj

       }

  

  继承的方式基本就这三种,在这三种的基础上还可以去延伸更过的方法,比如将以上方法组合,或者利用 for ... in ... 遍历一个构造函数,然后去赋值给其中的一个构造函数的原型等等;

  在继承中我们经常要考虑的一个问题就是 this 转向的问题,进行 this 转向的时候用到的方法基本就是 call 和 apply;

  call 和 apply 方法其实来源本身就都是继承于 Funcition.prototype ,所以在 数组、对象、函数中是都可以使用 call 和 apply 的;

  call 和 apply 的作用都是指定函数内部的 this,进行 this 转向新的实例对象;区别就在于,call 方法除了接收 this 参数外,还可以接收很多的参数,而 apply 除了接收 this 参数外,其余的参数需要通过数组的形式进行传递;例如:

    parament.call(this, 2, 3, 4)        parament.apply(this, [ 2, 3, 4])

   例如: es5原型以及原型链

function objParent () {
    this.nationality = 'China';
  }
  objParent.prototype.objParentType = _ =>'原型 of parent';

  var objParentA = new objParent();

  // 通过原型链继承
  function objChild (name) {
    this.name = name;
    this.age = 10;
    this.sex = '男';
    this.indocFn = function () {
      return 'my name is child, and I am is a student in shenglilu school.'
    }
  }
  objChild.prototype = new objParent();

  // 通过 call 继承,和原型链继承的区别就是不能继承父类的原型
  // function objChild (name) {
  //   objParent.call(this); // 继承objParent
  //   this.name = name;
  //   this.age = 10;
  //   this.sex = '男';
  //   this.indocFn = function () {
  //     return 'my name is child, and I am is a student in shenglilu school.'
  //   }
  // }

  objChild.prototype.address = '上海市徐汇区'; // 定义objChild 的原型

  var objChildA = new objChild('child-A');
  console.log(objChildA.__proto__.__proto__.objParentType()); // 原型 of parent

  es6 的原型以及原型链

class objParent {
    constructor (x, y) {
      this.nationality = 'China';
    }
    objParentType () {
      return '原型 of parent';
    } 
  }

  var objParentA = new objParent();
  console.log(objParentA);

  class objChild extends objParent {
    constructor(x, y, name) {
      super(x, y); // 将this 指向 objChild 的同时,向父类中传递参数
      this.name = name;
      this.age = 10;
      this.sex = '男';
    }
    indocFn () {
      return 'my name is child, and I am is a student in shenglilu school.'
    }
  }

  var objChildA = new objChild( 'x', 'y','child-A');
  console.log(objChildA.__proto__.__proto__.objParentType()); // 原型 of parent

  

原文地址:https://www.cnblogs.com/mufc/p/10647693.html