搞懂 js apply、call、bind

112 阅读3分钟

applycallbind都是可以改变this指向的,具体该怎么用呢?先看下面的例子:

var name="lucy";
let obj={
 name:"martin",
 say:function () {
 console.log(this.name);
 }
};
obj.say(); //martin,this指向obj对象
setTimeout(obj.say,0); //lucy,this指向window对象

可以看到,正常情况下 say 方法中的 this 是指向调用它的 obj 对象的,所以输出符合我们的预期,打印出obj.name
而定时器 setTimeout 中的 say 方法中的 this 是指向window对象的(在浏览器中),这是因为 say 方法在定时器中是作为回调函数来执行的,因此回到主栈执行时是在全局执行上下文的环境中执行的,所以打印的是window.name,即lucy,这并不符合我们的预期,因此我们需要修改 this 的指向。

apply

apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入,且当第一个参数为nullundefined的时候,默认指向window(在浏览器中),使用apply方法改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次。

var name="martin";
var obj={
 name:"lucy",
 say:function(year,place){
 console.log(this.name+" is "+year+" born from "+place);
 }
};
var say=obj.say;
setTimeout(function(){
 say.apply(obj,["1996","China"])
} ,0); //lucy is 1996 born from China,this改变指向了obj
say("1996""China") //martin is 1996 born from China,this指向window,说明apply只是临时改变一次this指向

可以看到,apply第二个参数是数组,apply后打印的是obj.name,如果没有apply,那么打印的就是window.name

call

call函数的作用与apply是一致的,只是参数形式的区别。call方法的第一个参数也是this的指向,后面传入的是一个参数列表。当第一个参数为nullundefined的时候,默认指向window(在浏览器中),使用apply方法改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次。

var arr=[1,10,5,8,3];
console.log(Math.max.call(null,arr[0],arr[1],arr[2],arr[3],arr[4])); //10

bind

bind,顾名思义,绑定的意思。它会返回一个永久绑定this指向的函数,函数声明:func.bind(thisArg, arg1, arg2, ...)。语法跟callapply类似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数。

const person = {
    name: 'YuTengjing',
    age: 22,
};
​
function introduce() {
    console.log(`Hello everyone! My name is ${this.name}. I'm ${this.age} years old.`);
}
​
const myFriend = { name: 'dongdong', age: 21 };
person.introduce = introduce.bind(myFriend);
​
// person.introduce 的 this 已经被绑定到 myFriend 上了
console.log(person.introduce()); // => Hello everyone! My name is dongdong. I'm 21 years old.
console.log(person.introduce.call(person)); // => Hello everyone! My name is dongdong. I'm 21 years old. 

apply,call,bind三者的区别

  • 三者都可以改变函数的this对象指向。
  • 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefinednull,则默认指向全局window
  • 三者都可以传参,但是apply是数组,而call是参数列表,且applycall是一次性传入参数,而bind可以分为多次传入。
  • bind 是返回绑定this之后的函数,便于稍后调用;applycall 则是立即执行 。