js的继承方法小结(prototype、call、apply)

js的原型继承 -- prototype数组

先说下什么是prorotype?bash

  1. js中,俗话说“一切皆对象”。用new 出来的都是函数对象;不然就是普通对象
  2. 函数对象都有prototype(原型对象);而普通对象则只有__proto__(原型指针)
  3. 函数对象的一个特色:能够实现不一样类之间的方法继承
  4. 函数的子类能够共享父类的方法,而父类不能想用子类的方法
eg: (prototype的继承)
 
 //建立父类函数对象    
  function Personal(name, age) {
    this.name = name;     //父类的私有属性
    this.age = age;
    this.house = ['北京', '上海']
  }
  Personal.prototype.run = function() {   //给父类原型动态添加方法
    alert('原型方法:' + this.name + ' is running!');
  }
  var per = new Personal('小白', 24)
  per.run() //打印 --> 原型方法:小白 is running!
  
 //建立子类函数对象
  function Boy() {}
  Boy.prototype = new Personal('小黑', 19) //子类继承父类的全部属性和方法
  Boy.prototype.source = 100            //给子类添加原型属性
  Boy.prototype.printSource = function() {  //给子类添加方法
    alert(this.name + '的原型方法printSouce打印成绩为:' + this.source) //小黑的原型方法printSouce打印成绩为:100
  }
  Boy.prototype.run()   //打印 --> 原型方法:小黑 is running!
  var boys = new Boy()
  boys.printSource()
  console.log(boys, '--boys---') //打印 -->19, 小黑, 100 (这里会沿着prototype向上查找到Personal的属性)
复制代码

如下是关于prototype继承须要注意的点:微信

  1. 若是父类中有引用类型的属性:Array,Object等。子类继承了这些属性,并尝试改变的话,会影响到父类的属性。
//建立另一个实例1:
      var boys1 = new Boy()
      boys1.house.push('深圳')
//打印这两个实例:
      console.log(boys, boys1)
复制代码

能够看出来,当属性为引用类型时,只要有一个实例的属性作了操做,全部的实例都会受到影响。app

  1. 该方式致使 Boy.prototype.constructor 被重写,它指向的是 Personal 而非 Boy。所以你须要手动将 Boy.prototype.constructor 指回 Boy。
Boy.prototype = new Personal();
Boy.prototype.constructor === Personal; // true

// 重写 Boy.prototype 中的 constructor 属性,指向本身的构造函数 Boy
Boy.prototype.constructor = Boy;
复制代码
  1. 由于 Boy.prototype = new Personal(); 重写了 Boy 的原型对象,因此 printSource 放在重写原型对象以前会被覆盖掉,所以给子类添加原型方法必须在替换原型以后(eg是没有被覆盖的)。
function Boy() {}
Boy.prototype = new Personal();

// 给子类添加原型方法必须在替换原型以后
Boy.prototype.printSource = function() {
  console.log('printSource~');
};

复制代码
  1. 建立 boys 实例时没法向父类的构造函数传参,也就是没法初始化 source属性。所以:只能建立实例以后再修改父类的属性。
const boys = new Boy();

// 只能建立实例以后再修改父类的属性
boys.source = 100;
复制代码

apply()、call()方法的继承函数

了解下apply()、call()方法this

  1. apply()、call()的用法:
obj.call(thisObj, arg1, arg2, ...);
obj.apply(thisObj, [arg1, arg2, ...]);
复制代码

obj是父级,thisObj是子级;第二个参数apply能够接收一个数组,而call只能是每项逐个接收。spa

  1. apply和call 原本就是为了扩展函数的做用域而生的,换句话说就是为了改变this的指向存在的。
  2. 当一个object没有某种方法,可是其余的有,咱们能够借助call和apply来用其余对象的方法来作操做,也能够传参数。
//eg:
function Personal(name, sex) {
      this.name = name;
      this.sex = sex;
      this.say = function (){
        alert('姓名:' + this.name + ';性别:' + this.sex)
      }
    }
    const per = new Personal('Allan', '男')
    per.say();
    
//apply()方法实现:
    function Girls(name, sex) {
      Personal.apply(this, [name, sex]);
      //Person.apply(this,arguments); //跟上句同样的效果,arguments  
      //Print.apply(this,arguments);  //还能够实现继承多个父类,可是原型 prototype只能继承一个父类!!!切记
    }
    const girls1 = new Girls('Lucy', '女')
    girls1.say();
    
//call()实现:
    function Boy(name, sex) {
      Personal.call(this, name, sex);
    }
    const boys = new Boy('Barry', '男');
    boys.say() //
复制代码

总结prototype

  1. prototype能够动态的给对象增长属性和方法。
  2. 能够实现子类继承父类,拥有父类的属性和方法。
  3. call和apply的区别,在于参数的不一样。
  4. call和apply,理解为在子类的运行环境中执行父类的方法和属性。
  5. call和apply能够实现一个子类继承多个父类,可是prototype只能有一个父类。

若是以为对你有帮助,请给做者一点小小的鼓励,点个赞或者收藏吧。
(有须要沟通的请联系我:微信( wx9456d ) 邮箱( allan_liu986@163.com )
指针

相关文章
相关标签/搜索