call、apply、bind区别

201 阅读4分钟

call、apply、bind区别

call(无数个参数):第一个参数:改变this指向;第二个参数:实参;使用后自动执行该函数。

apply(两个参数):第一个参数:变this指向;第二个参数:数组(里面为实参);使用时自动执行该函数。

bind(无数个参数):第一个参数:改变this指向;第二个参数:实参,返回值为一个新的函数;使用时需要手动调用下返回的新函数。

  var name = '小张',age = 18;
  var obj = {
     name = '小王',
     objName = this.age,
     myFun:function(){
       console.log(this.name+'年龄'+this.age);
     }
  }
  
  obj.objAge;                //18
  obj.myFun();               //小王年龄undefined
  
  
  
  
  var name = '小赵';
  function nameFun(){
    console.log(this.name)
  }
   
  nameFun();                 //小赵

改变this指向

  var name = '小张',age = 18;
  var obj = {
     name = '小王',
     objName = this.age,
     myFun:function(){
       console.log(this.name+'年龄'+this.age);
     }
  }
  
  var newObj = {
    name:'张三',
    age:99
  }
  
  
  obj.myFun.call(newObj);                  //张三年龄99
  obj.myFun.apply(newObj);                 //张三年龄99
  obj.myFun.bind(newObj)();              //张三年龄99

bind返回的是一个新的函数,必须调用才会被执行。

  var name = '小张',age = 18;
  var obj = {
     name = '小王',
     objName = this.age,
     myFun:function(){
       console.log(this.name+'年龄'+this.age,'来自"+from + '去往' + to);
     }
  }
  
  var newObj = {
    name:'张三',
    age:99
  }
  
  
  obj.myFun.call(newObj,'成都','上海');              //张三年龄99,来自成都去往上海
  obj.myFun.apply(newObj,['成都','上海']);           //张三年龄99,来自成都去往上海
  obj.myFun.bind(newObj,'成都','上海')();            //张三年龄99,来自成都去往上海
  obj.myFun.bind(newObj,['成都','上海'])();          //张三年龄99,来自成都上海,去往undefined

1、call

语法:functionFun.call(thisArg,arg1,arg2,...)

用法:用来在调用函数时,临时替换一次函数内部的this。

参数:1、thisArg:调用时用来替换函数内部的this值。 2、arg1,arg2,...:指定的参数列表。

返回值:使用调用者提供的this值和参数调用该函数的返回值。若该方法没有返回值,则返回undefined

   function calc(base,bonus1,bonus2){
      console.log(`${this.ename}的总工资是:${base+bonus1+bonus2}`)
   }
   
   var obj = {
      ename:'lili'
   }
   
   calc.call(obj,1000,1200,2300);                 //lili的总工资是4500
   //错误写法:obj.calc(1000,1200,2300),因为calc这个方法在全局对象中存在,不在obj的原型链上

2、apply

语法:functionFun.apply(thisArg,arr)

用法:调用函数时,改变函数内部this指向

参数:1、thisArg:改变函数内部this指向。 2、arr:传入的参数,数组格式。

返回值:使用调用者提供的this值和参数调用该函数的返回值。若该方法没有返回值,则返回undefined

   function calc(base,bonus1,bonus2){
      console.log(`${this.name}的总工资是:${base+bonus1+bonus2}`)
   }
   
   let obj = {
      ename:'张'
   }
   
   calc.apply(obj,[1000,2000,3000]);              //长得总工资是:6000

apply和call相同点都是能临时替换一次函数中的this。只不过apply比call多一项功能---先打算数组为单个值,再分别传给函数实参。

3、bind

语法:var newfunctionFun = functionFun.bind(thisArg,arg1,arg2,...)

用法:创建一个和原函数一模一样的新函数,将新函数中的this永久替换为指定的对象

参数:1、thisArg:改变this指向; 2、arg1,arg2,... :指定的参数列表

返回值:使用调用者提供的this值和参数调用该函数的返回值。若该方法没有返回值则返回undefined

bind只创建新函数,不会改变原函数。

   function calc(base,bonus1,bonus2){
      console.log(`${this.name}的总工资是:${base+bonus1+bonus2}`)
   }
   
   let obj = {
      ename:'张'
   }
   
   let lcalc = calc.bind(obj,10000);
   //新函数  function lcalc(base,bonus1,bonus2){
   //          this.ename永久替换为obj.ename
   //          形参base永久为10000
   //}
   
   //此后再调用lcalc时,无需反复.call(obj,10000),其中this指向永远指obj,base永远是10000
   lcalc(2000,3000);                     //张的总工资是:15000
   lcalc(1000,6000);                     //张的总工资是:17000

bind的一个重要区别是后面传入这个参数列表可以分次传入,call和apply必须一次性传入所有参数。

   var arr = [1,10,5,8,12];
   var max = Math.max.bind(null,arr[0],arr[1],arr[2],arr[3])
   console.log(max(arr[4]));               // 12  分两次传参
   //bind方法可以分多次传参,最后函数运行时会把所有参数连接起来一起放入函数运行。

应用场景

1、数组之间追加
   var arr = [12,'foo',{name:'Joe',-2548}];
   var arr2 = ['Doe',555,100];
   Array.prototype.push.apply(arr,arr2);
   //[12,'foo',{name:'Joe',-2548},'Doe',555,100]
2、获取数组中的最大值和最小值
   var numbers = [5,548,120,-215];
   var maxInNumbers = Math.max.apply(Math,numbers);             //548
   minInNumbers = Math.max.call(Math,5,548,120,-215);          //548

总结:

1、相同点:

  1. 都可以改变函数内部的this指向;
  2. 第一个参数都是自定函数内部中this的指向

2、区别:

1)一个函数被call/apply的时候会立即执行函数,bind不会调用函数,但bind会创建一个和原函数一模一样仅仅改变了this指向的新函数,然后在需要的时候调用新函数执行。

2)call/apply/bind传递的参数不通,call和bind调用时接收的是指定的参数列表,apply调用时接收的是一个数组,apply可以打散其接收到的数组成为单个值,再分别传给函数实参。