一、作用
call、apply、bind作用是改變函數(shù)執(zhí)行時(shí)的上下文,簡(jiǎn)而言之就是改變函數(shù)運(yùn)行時(shí)的this指向
那么什么情況下需要改變this的指向呢?下面舉個(gè)例子
var?name="lucy";
const?obj={
????name:"martin",
????say:function(){
????????console.log(this.name);
????}
};
obj.say();?//martin,this指向obj對(duì)象
setTimeout(obj.say,0);?//lucy,this指向window對(duì)象
從上面可以看到,正常情況say方法輸出martin
但是我們把say放在setTimeout方法中,在定時(shí)器中是作為回調(diào)函數(shù)來執(zhí)行的,因此回到主棧執(zhí)行時(shí)是在全局執(zhí)行上下文的環(huán)境中執(zhí)行的,這時(shí)候this指向window,所以輸出luck
我們實(shí)際需要的是this指向obj對(duì)象,這時(shí)候就需要該改變this指向了
setTimeout(obj.say.bind(obj),0);?//martin,this指向obj對(duì)象
二、區(qū)別
下面再來看看apply、call、bind的使用
apply
apply接受兩個(gè)參數(shù),第一個(gè)參數(shù)是this的指向,第二個(gè)參數(shù)是函數(shù)接受的參數(shù),以數(shù)組的形式傳入
改變this指向后原函數(shù)會(huì)立即執(zhí)行,且此方法只是臨時(shí)改變this指向一次
functionfn(...args){
????console.log(this,args);
}
let?obj?=?{
????myname:"張三"
}
fn.apply(obj,[1,2]);?// this會(huì)變成傳入的obj,傳入的參數(shù)必須是一個(gè)數(shù)組;
fn(1,2)?//?this指向window
當(dāng)?shù)谝粋€(gè)參數(shù)為null、undefined的時(shí)候,默認(rèn)指向window(在瀏覽器中)
fn.apply(null,[1,2]);?//?this指向window
fn.apply(undefined,[1,2]);?//?this指向window
call
call方法的第一個(gè)參數(shù)也是this的指向,后面?zhèn)魅氲氖且粋€(gè)參數(shù)列表
跟apply一樣,改變this指向后原函數(shù)會(huì)立即執(zhí)行,且此方法只是臨時(shí)改變this指向一次
functionfn(...args){
????console.log(this,args);
}
let?obj?=?{
????myname:"張三"
}
fn.call(obj,1,2);?// this會(huì)變成傳入的obj,傳入的參數(shù)必須是一個(gè)數(shù)組;
fn(1,2)?//?this指向window
同樣的,當(dāng)?shù)谝粋€(gè)參數(shù)為null、undefined的時(shí)候,默認(rèn)指向window(在瀏覽器中)
fn.call(null,[1,2]);?//?this指向window
fn.call(undefined,[1,2]);?//?this指向window
bind
bind方法和call很相似,第一參數(shù)也是this的指向,后面?zhèn)魅氲囊彩且粋€(gè)參數(shù)列表(但是這個(gè)參數(shù)列表可以分多次傳入)
改變this指向后不會(huì)立即執(zhí)行,而是返回一個(gè)永久改變this指向的函數(shù)
functionfn(...args){
????console.log(this,args);
}
let?obj?=?{
????myname:"張三"
}
const?bindFn?=?fn.bind(obj);?//?this?也會(huì)變成傳入的obj?,bind不是立即執(zhí)行需要執(zhí)行一次
bindFn(1,2)?//?this指向obj
fn(1,2)?//?this指向window
小結(jié)
從上面可以看到,apply、call、bind三者的區(qū)別在于:
三者都可以改變函數(shù)的this對(duì)象指向
三者第一個(gè)參數(shù)都是this要指向的對(duì)象,如果如果沒有這個(gè)參數(shù)或參數(shù)為undefined或null,則默認(rèn)指向全局window
三者都可以傳參,但是apply是數(shù)組,而call是參數(shù)列表,且apply和call是一次性傳入?yún)?shù),而bind可以分為多次傳入
bind是返回綁定this之后的函數(shù),apply、call?則是立即執(zhí)行