apply、call、bind都是可以改变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的指向,第二个参数是函数接受的参数,以数组的形式传入,且当第一个参数为null、undefined的时候,默认指向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的指向,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向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, ...)。语法跟call、apply类似,第一参数也是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要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window。 - 三者都可以传参,但是
apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入。 bind是返回绑定this之后的函数,便于稍后调用;apply、call则是立即执行 。