call,apply,bind的区别

104 阅读2分钟

问题:js中this有很多种情况? 但是,有时候默认的this情况不是我们想要的,如何解决这个问题?

解决: 其实js中专门提供了一组函数,用来修改你不想要的this,改成想要的对象(包括3种情况:call,bind,apply)。

call()

  1. 在一次调用函数时,临时替换一次this为指定的对象 函数本次调用后,this恢复原样,要调用的函数.call(替换this的对象,实参值列表)

原理 .call() 做了三件事:

  1. 调用一次函数立即执行

  2. 替换函数中的this为call 的第一个参数对象

  3. 将call的第二个参数开始所有其余的实参值都出传给要调用的函数作为实参值。

示例使用call修改函数中的this ->x想要的对象
//有一个公共计算薪资的函数
//底薪      奖金1    奖金2
function  jisuan(base,bonus1,bonus2 ){
    console.log(`{ this.ename}`的总共工资是:`${base+bonus1+bonus2}`);
} 	
var lilei ={ename: "Li  Lei"}
错误:
    (1 ) jisuan(1000,100,200)  //this ->window 
    (2 ) lilei.jisuan(1000,100,200) //  报错 lile.jisuan   is not a  function  
    // 因为jisuan函数没有在李磊自已身上 也没有在李磊的父亲身上   //而是在window的全局对象中 所以也报错
正确做法:
    jisuan.call(lilei,1000,100,2000) //  将lilei替换为this

问题如果要传入多个实参值是放在数组里面的,需要先拆分数组,在传参中出现不一致,都用apply代替call,要调用的函数.apply(替换this的对象,数组)

apply 原理 三件事:

  1. 调用函数
  2. 替换this为指定对象
  3. 先拆散数组,在分别传参给要调用的函数
示例
    //有一个公共计算薪资的函数 底薪      奖金1    奖金2
function  jisuan(base,bonus1,bonus2 ){
    console.log(`{ this.ename}`的总共工资是:`${base+bonus1+bonus2}`);
} 
var lilei ={ename: "Li  Lei"}
var arr =[1000,220,233]
jisuan.apply(lilei,arr)

如果每次都要用call替换this很麻烦,就可以用bind()创建一个只属于某个对象的函数。当这个对象再使用函数,就不用反复call了

bind( )先创建一个和原函数功能一样的新函数副本,并且永久将函数中的this替换为指定的新对象,var 新函数副本 = 原函数.bind(替换this的新对象)

原理两件事

  1. 创建了一个和原函数完全一样的新函数副本,永久替换新函数副本中的this为指定对象
  2. 在反复调用新函数副本,而不用每次都用call 新函数副本(实参值,...)

其实bind()不但可以永久绑定this,还可以永久绑定部分实参值

var 新函数副本 = 原函数.bind(替换this的对象,固定实参值) 三件事

  1. 创建了一个和原函数完全一样的新函数副本
  2. 永久替换新函数副本中的this为指定对象
  3. 将固定的实参值永久绑定到对应位置的形参变量上

调用函数副本时,既不用call(),又不用传固定的参数值,只需要传递剩余的不固定的个别实参值即可! 新函数副本(剩余不固定的实参值)

// 示例永久绑定this并永久绑定实参值 
function jisuan(base, bonus1, bonus2){
    console.log(`${this.ename}的总工资是:${base+bonus1+bonus2}`);
    
}
var lilei={ename:"LiLei"};
var jisuan2=jisuan.bind(lilei,10000);