深入js中的call,apply方法

作者: luichooy | 来源:发表于2017-10-24 14:42 被阅读49次

    call(),apply()方法的作用都是用来改变函数运行时的上下文(Context),那么什么是上下文呢?

    关于上下文

    上下文就是函数中this的值,它的值等于函数运行时,调用这个函数的对象,也就是说,上下文是可以动态改变的,随着函数执行环境的不同,它的值也会发生变化。比如:

    1. 在全局作用于中调用函数,函数的上下文为Global对象(在浏览器中为window对象),eg:
    var name = 'JavaScript';
    function sayName (){
      console.log(this.name);
    }
    // 在全局作用域中调用sayName,此时相当与window.sayName();
    // 所以此时的 this = window,即函数运行时的上下文为: window对象
    sayName();     
    
    1. 在特定对象中调用函数,this指向这个对象,eg:
    function Cat(name,sound) {
      this.name = name;
      this.sound = sound;
    }
    Cat.prototype.speak =function () {
      console.log(`${this.name} speak ${this.sound}`);
    }
    var mipang = new Cat('mipang','喵喵喵~~');
    // 在对象mipang中调用函数speak,此时函数speak内部的指针指向mipang
    // mipang有两个属性,name:'mipang',sound:'喵喵喵~~';
    // 所以输出是: mipang speak 喵喵喵!!
    mipang.speak();
    

    call()、apply()语法

    通过上面的例子,我们对上下文有了一个基本概念,此时我们再来讨论call(),apply()
    如一开始所说,call()和apply()都是用来改变函数执行时的上下文的,两者的区别是传参方式的不同:

    // call()具有多个参数,apply方法只有两个参数;
    // 两者的第一个参数都是一个对象obj,用来改变函数function的上下文;
    // 即 函数function中的this指向obj对象;
    
    function.call(obj,arg1,arg2,arg3,...);   // 第一个参数后面的参数是一个参数列表
    function.apply(obj,[arg1,arg2,arg3,...])  // 第二个参数是一个数组,数组的元素为函数的参数,即将call()方法的参数列表写成数组形式
    

    我们举个例子来说一下call和apply的具体用法:

    // 创建对象bajie,bajie有个introduce方法可以用来介绍自己的光辉事迹
    var bajie = {
      name:  '猪八戒',
      introduce:  function (job,ability) {
        console.log(job + this.name + ability);
      }
    }
    bajie.introduce('天蓬大元帅','调戏嫦娥仙子'); //天蓬大元帅猪八戒调戏嫦娥仙子
    
    // 创建对象wukong,wukong并没有一个介绍自己光辉事迹的introduce方法
    var wukong = {
      name: '孙悟空'
    }
    

    假设我们想让wukong也有办法来介绍自己的光辉事迹,可以给对象wukong添加一个相同的introduce方法
    假设我们也想给牛魔王、白骨精、金角大王等等相同的能力,难道要分别给每一个创建这个方法吗?当然不是,这个时候call(),apply()就派上用场了:

    bajie.introduce.call(wukong,'齐天大圣','调戏嫂嫂铁扇公主');
    bajie.introduce.apply(wukong,['齐天大圣','调戏嫂嫂铁扇公主']);
    // 齐天大圣孙悟空调戏嫂嫂铁扇公主
    

    我们来看一个实际应用场景:

    function Animal(name,food,sound){
      this.name = name;
      this.food = food;
      this.sound = sound;
    }
    Animal.prototype.speak = function() {
      console.log(this.name+'爱吃'+this.food+'    '+this.sound);
    }
    function Cat(name,food,sound) {
      // Animal.call(this,name,food,sound);
      Animal.apply(this,arguments);
    }
    Cat.prototype = new Animal();
    var cat = new Cat('咪胖','鱼','喵喵喵~');
    cat.speak();   // 咪胖爱吃鱼    喵喵喵~
    

    apply()方法特性:

    apply方法会将默认将参数数组转换为参数列表,利用这一特性,有下面几个应用:

    1. 数组合并:
    var arr1 = [1,2,3];
    var arr2 = [4,5,6];
    // 因为push()方法只接受参数列表,利用apply的特性将数组参数转为参数列表
    arr1.push.apply(arr1,arr2);
    // 或者Array.prototype.push.apply(arr1,arr2);
    console.log(arr1);  // [1,2,3,4,5,6]
    
    // 该方法接受参数列表,并将参数列表转为数组返回
    function transtoArray(){
      var values = new Array();
      values.push.apply(values,arguments);
      return values;
    }
    
    var arr = transtoArray('张三','李四','王五','赵六');
    console.log(arr);   // ['张三','李四','王五','赵六']
    
    1. 求的数组中的最大值和最小值
    var arr = [1,8,5,4,5,9,6,3,7];
    var maxValue = Math.max.apply(null,arr);
    console.log(maxValue);   // 9
    var minValue = Math.min.apply(null,arr);
    console.log(minValue);   // 1
    

    相关文章

      网友评论

        本文标题:深入js中的call,apply方法

        本文链接:https://www.haomeiwen.com/subject/jqhtpxtx.html