JavaScript中call,apply,bind方法的總結(jié)

一般用來指定this的環(huán)境算凿,在沒有學(xué)之前囱井,通常會(huì)有這些問題。

var a = {
    user:"追夢(mèng)子",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
b(); //undefined

我們是想打印對(duì)象a里面的user卻打印出來undefined是怎么回事呢?如果我們直接執(zhí)行a.fn()是可以的晚顷。

var a = {
    user:"追夢(mèng)子",
    fn:function(){
        console.log(this.user);
    }
}
a.fn(); //追夢(mèng)子

這里能夠打印是因?yàn)榉寤铮@里的this指向的是函數(shù)a艾扮,那為什么上面的不指向a烛亦?我們?nèi)绻枰私鈚his的指向問題脂矫,請(qǐng)看徹底理解js中this的指向疲憋,不必硬背這篇文章擅憔。
雖然這種方法可以達(dá)到我們的目的具伍,但是有時(shí)候我們不得不將這個(gè)對(duì)象保存到另外的一個(gè)變量中萤皂,那么就可以通過以下方法敛苇。

1叽赊、call()
(1)call 方法可以用來代替另一個(gè)對(duì)象調(diào)用一個(gè)方法恋沃。call 方法可將一個(gè)函數(shù)的對(duì)象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對(duì)象。

obj1.method1.call(obj2,argument1,argument2)

如上必指,call的作用就是把obj1的方法放到obj2上使用囊咏,后面的argument1..這些做為參數(shù)傳入.

舉一個(gè)具體的例子

function add(a, b) { 
    alert(a + b); 
} 
function sub(a, b) { 
    alert(a - b); 
} 
add.call(sub, 3, 1); 

這個(gè)例子中的意思就是用 add 來替換 sub,add.call(sub,3,1) == add(3,1) 塔橡,所以運(yùn)行結(jié)果為:alert(4); // 注意:js 中的函數(shù)其實(shí)是對(duì)象梅割,函數(shù)名是對(duì) Function 對(duì)象的引用。

看一個(gè)稍微復(fù)雜一點(diǎn)的例子

function Class1()  { 
    this.name = "class1"; 
    this.showNam = function() { 
        alert(this.name); 
    } 
} 
function Class2()  { 
    this.name = "class2"; 
} 
var c1 = new Class1(); 
var c2 = new Class2(); 
c1.showNam.call(c2); 

注意葛家,call 的意思是把 c1 的方法放到c2上執(zhí)行户辞,原來c2是沒有showNam() 方法,現(xiàn)在是把c1 的showNam()方法放到 c2 上來執(zhí)行癞谒,所以this.name 應(yīng)該是 class2底燎,執(zhí)行的結(jié)果就是 :alert("class2");

還有更有趣的,可以用 call 來實(shí)現(xiàn)繼承

function Class1()  { 
    this.showTxt = function(txt) { 
        alert(txt); 
    } 
} 
function Class2()  { 
    Class1.call(this); 
} 
var c2 = new Class2(); 
c2.showTxt("cc"); 

這樣 Class2 就繼承Class1了弹砚,Class1.call(this) 的 意思就是使用 Class1 對(duì)象代替this對(duì)象双仍,那么 Class2 中不就有Class1 的所有屬性和方法了嗎,c2 對(duì)象就能夠直接調(diào)用Class1 的方法以及屬性了桌吃,執(zhí)行結(jié)果就是:alert(“cc”);

對(duì)的朱沃,就是這樣,這就是 javaScript 如何來模擬面向?qū)ο笾械睦^承的茅诱,還可以實(shí)現(xiàn)多重繼承为流。

function Class10()  { 
    this.showSub = function(a,b)  { 
        alert(a-b); 
    } 
} 
function Class11()  { 
    this.showAdd = function(a,b) { 
        alert(a+b); 
    } 
} 
function Class2()  { 
    Class10.call(this); 
    Class11.call(this); 
} 

很簡(jiǎn)單,使用兩個(gè) call 就實(shí)現(xiàn)多重繼承了
當(dāng)然让簿,js的繼承還有其他方法,例如使用原型鏈秀睛,這個(gè)不屬于本文的范疇尔当,只是在此說明call 的用法
說了call ,當(dāng)然還有 apply,這兩個(gè)方法基本上是一個(gè)意思
區(qū)別在于 call 的第二個(gè)參數(shù)可以是任意類型椭迎,而apply的第二個(gè)參數(shù)必須是數(shù)組

(2)

var a = {
    user:"追夢(mèng)子",
    fn:function(){
        console.log(this.user); //追夢(mèng)子
    }
}
var b = a.fn;
b.call(a);

通過在call方法锐帜,給第一個(gè)參數(shù)添加要把b添加到哪個(gè)環(huán)境中,簡(jiǎn)單來說畜号,this就會(huì)指向那個(gè)對(duì)象缴阎。
call方法除了第一個(gè)參數(shù)以外還可以添加多個(gè)參數(shù),如下:

var a = {
    user:"追夢(mèng)子",
    fn:function(e,ee){
        console.log(this.user); //追夢(mèng)子
        console.log(e+ee); //3
    }
}
var b = a.fn;
b.call(a,1,2);

2简软、apply()

var a = {
    user:"追夢(mèng)子",
    fn:function(){
        console.log(this.user); //追夢(mèng)子
    }
}
var b = a.fn;
b.apply(a);

同樣apply也可以有多個(gè)參數(shù)蛮拔,但是不同的是,第二個(gè)參數(shù)必須是一個(gè)數(shù)組痹升,如下:

var a = {
    user:"追夢(mèng)子",
    fn:function(e,ee){
        console.log(this.user); //追夢(mèng)子
        console.log(e+ee); //11
    }
}
var b = a.fn;
b.apply(a,[10,1]);

或者

var a = {
    user:"追夢(mèng)子",
    fn:function(e,ee){
        console.log(this.user); //追夢(mèng)子
        console.log(e+ee); //520
    }
}
var b = a.fn;
var arr = [500,20];
b.apply(a,arr);

//注意如果call和apply的第一個(gè)參數(shù)寫的是null建炫,那么this指向的是window對(duì)象

var a = {
    user:"追夢(mèng)子",
    fn:function(){
        console.log(this); //Window {external: Object, chrome: Object, document: document, a: Object, speechSynthesis: SpeechSynthesis…}
    }
}
var b = a.fn;
b.apply(null);

3、bind()
bind方法和call疼蛾、apply方法有些不同肛跌,但是不管怎么說它們都可以用來改變this的指向。
先來說說它們的不同吧察郁。

var a = {
    user:"追夢(mèng)子",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
b.bind(a);

我們發(fā)現(xiàn)代碼沒有被打印衍慎,對(duì),這就是bind和call皮钠、apply方法的不同稳捆,實(shí)際上bind方法返回的是一個(gè)修改過后的函數(shù)。

var a = {
    user:"追夢(mèng)子",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
var c = b.bind(a);
console.log(c); //function() { [native code] }

那么我們現(xiàn)在執(zhí)行一下函數(shù)c看看鳞芙,能不能打印出對(duì)象a里面的user

var a = {
    user:"追夢(mèng)子",
    fn:function(){
        console.log(this.user); //追夢(mèng)子
    }
}
var b = a.fn;
var c = b.bind(a);
c();

ok眷柔,同樣bind也可以有多個(gè)參數(shù),并且參數(shù)可以執(zhí)行的時(shí)候再次添加原朝,但是要注意的是驯嘱,參數(shù)是按照形參的順序進(jìn)行的。

var a = {
    user:"追夢(mèng)子",
    fn:function(e,d,f){
        console.log(this.user); //追夢(mèng)子
        console.log(e,d,f); //10 1 2
    }
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);

總結(jié):call和apply都是改變上下文中的this并立即執(zhí)行這個(gè)函數(shù)喳坠,bind方法可以讓對(duì)應(yīng)的函數(shù)想什么時(shí)候調(diào)就什么時(shí)候調(diào)用鞠评,并且可以將參數(shù)在執(zhí)行的時(shí)候添加,這是它們的區(qū)別壕鹉,根據(jù)自己的實(shí)際情況來選擇使用剃幌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晾浴,隨后出現(xiàn)的幾起案子负乡,更是在濱河造成了極大的恐慌,老刑警劉巖脊凰,帶你破解...
    沈念sama閱讀 223,207評(píng)論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抖棘,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)切省,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門最岗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人朝捆,你說我怎么就攤上這事般渡。” “怎么了芙盘?”我有些...
    開封第一講書人閱讀 170,031評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵驯用,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我何陆,道長(zhǎng)晨汹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,334評(píng)論 1 300
  • 正文 為了忘掉前任贷盲,我火速辦了婚禮淘这,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巩剖。我一直安慰自己铝穷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評(píng)論 6 398
  • 文/花漫 我一把揭開白布佳魔。 她就那樣靜靜地躺著曙聂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鞠鲜。 梳的紋絲不亂的頭發(fā)上宁脊,一...
    開封第一講書人閱讀 52,895評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音贤姆,去河邊找鬼榆苞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛霞捡,可吹牛的內(nèi)容都是我干的坐漏。 我是一名探鬼主播,決...
    沈念sama閱讀 41,300評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼碧信,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼赊琳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起砰碴,我...
    開封第一講書人閱讀 40,264評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤躏筏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后呈枉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寸士,經(jīng)...
    沈念sama閱讀 46,784評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡檐什,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弱卡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,989評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡住册,死狀恐怖婶博,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荧飞,我是刑警寧澤凡人,帶...
    沈念sama閱讀 36,649評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站叹阔,受9級(jí)特大地震影響挠轴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜耳幢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評(píng)論 3 336
  • 文/蒙蒙 一岸晦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧睛藻,春花似錦启上、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至按摘,卻和暖如春包券,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背炫贤。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評(píng)論 1 275
  • 我被黑心中介騙來泰國(guó)打工溅固, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人照激。 一個(gè)月前我還...
    沈念sama閱讀 49,452評(píng)論 3 379
  • 正文 我出身青樓发魄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親俩垃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子励幼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容