JS函數(shù)之call()、apply()由驹、bind()

在對(duì)js深入學(xué)習(xí)時(shí)芍锚,發(fā)現(xiàn)有很多地方使用了call、apply和bind方法蔓榄。在此之前自己在項(xiàng)目開(kāi)發(fā)中卻很少使用到并炮,但是發(fā)現(xiàn)在很多源碼如vue中經(jīng)常會(huì)出現(xiàn)其用法,以及在面試中經(jīng)常會(huì)被提及甥郑,所以特在此記錄并學(xué)習(xí)一下逃魄。

-函數(shù)用法

首先,我們來(lái)看一個(gè)例子:

var name = "李四";
var person = {
        name:'張三',
        fn:function(){
          console.log(this.name)
        }
      }
person.fn();// 張三

對(duì)于上面代碼輸出的結(jié)果大家應(yīng)該不會(huì)有疑問(wèn)澜搅。再看下面:

var name = "李四";
var person = {
        name:'張三',
        fn:function(){
          console.log(this.name)
        }
      }
var fn =  person.fn;
fn();  //李四

這時(shí)候我們發(fā)現(xiàn)輸出的結(jié)果改變了伍俘,明明調(diào)用的是person的fn方法邪锌,為什么會(huì)輸出“李四”呢?
仔細(xì)觀察后我們不難發(fā)現(xiàn)問(wèn)題出在this身上癌瘾。
fn里的this指的是調(diào)用者觅丰,誰(shuí)調(diào)用了這個(gè)方法this就指向誰(shuí)。也就是說(shuō)妨退,在執(zhí)行person.fn()時(shí)妇萄,當(dāng)前調(diào)用者為person對(duì)象,此時(shí)person中有name屬性值為張三咬荷。而當(dāng)我們將person.fn賦值給新變量并直接調(diào)用時(shí)冠句,此時(shí)調(diào)用者為window對(duì)象,而window對(duì)象中name屬性值則為李四幸乒。
那怎么才能在第二種場(chǎng)景下也能輸出張三呢懦底?


1.call()

首先我們看下call()的用法:

var name = "李四";
var person = {
        name:'張三',
        fn:function(){
          console.log(this.name)
        }
      }
var fn =  person.fn;
fn.call(person); //張三

此時(shí)發(fā)現(xiàn)得到的正是我們想要的結(jié)果。
它的實(shí)現(xiàn)原理:通過(guò)call()方法改變了this(調(diào)用者)的指向罕扎。
通過(guò)call()方法調(diào)用fn方法并執(zhí)行聚唐,在call()方法中我們傳入了一個(gè)參數(shù):person,它就是調(diào)用者腔召,它可以將fn中的this由window對(duì)象改變成person對(duì)象拱层,因此在調(diào)用call()方法時(shí)我們將需要改變的this傳入即可。當(dāng)不傳參數(shù)或傳入null時(shí)宴咧,此時(shí)默認(rèn)this為window對(duì)象。


-支持傳入多個(gè)參數(shù)

當(dāng)person中方法帶有參數(shù)時(shí):

var name = "李四";
var person = {
        name:'張三',
        fn:function(gender,age){
          console.log(this.name+','+gender+','+age)
        }
      }
var fn =  person.fn;
fn.call(person,'男','25歲'); //張三径缅,男掺栅,25歲

傳入多個(gè)參數(shù)時(shí),第一個(gè)參數(shù)為調(diào)用者this,其后的參數(shù)為所調(diào)用的方法fn的參數(shù)纳猪。當(dāng)?shù)谝粋€(gè)參數(shù)傳null時(shí):

var name = "李四";
var person = {
        name:'張三',
        fn:function(gender,age){
          console.log(this.name+','+gender+','+age)
        }
      }
var fn =  person.fn;
fn.call(null,'男','25歲'); //李四氧卧,男,25歲氏堤,相當(dāng)于fn('男','25歲')
fn('男','25歲')沙绝;

第一個(gè)參數(shù)傳null時(shí)相當(dāng)于fn直接調(diào)用,不修改調(diào)用方this,但是一般在用call等方法時(shí)都是為了改變this指向鼠锈。

2.apply()

apply()方法和call()方法非常類(lèi)似:

var name = "李四";
var person = {
        name:'張三',
        fn:function(){
          console.log(this.name)
        }
      }
var fn =  person.fn;
fn.apply(person); //張三

調(diào)用時(shí)也一樣闪檬,但是在傳入多個(gè)參數(shù)時(shí)有區(qū)別

var name = "李四";
var person = {
        name:'張三',
        fn:function(gender,age){
          console.log(this.name+','+gender+','+age)
        }
      }
var fn =  person.fn;
fn.apply(person,['男','25歲']); //張三,男购笆,25歲

在對(duì)person中fn傳入?yún)?shù)時(shí)粗悯,必須以數(shù)組形式傳入,否則會(huì)報(bào)錯(cuò)同欠。

3.bind()

bind()方法也用于改變調(diào)用者this样傍,不同于call()和apply()方法横缔,它再使用時(shí),方法不會(huì)被立即調(diào)用衫哥,且返回一個(gè)新函數(shù)(this改變后的)茎刚,這樣就可以在需要使用的時(shí)候進(jìn)行調(diào)用,也就是先將需要改變的this綁定到方法上撤逢。

var name = "李四";
var person = {
        name:'張三',
        fn:function(){
          console.log(this.name)
        }
      }
var fn =  person.fn;
var newFn = fn.bind(person);
newFn ();//張三

多個(gè)參數(shù):

var name = "李四";
var person = {
        name:'張三',
        fn:function(gender,age){
          console.log(this.name+','+gender+','+age)
        }
      }
var fn =  person.fn;
var newFn = fn.bind(person);
newFn('男','25歲'); //張三膛锭,男,25歲

當(dāng)然在var newFn = fn.bind(person)時(shí)我們也可以直接傳入其它參數(shù):var newFn = fn.bind(person,'男','25歲')笛质,不過(guò)一般不建議這么使用泉沾,在bind時(shí)只做this改變綁定操作,fn方法的參數(shù)在新函數(shù)newFn調(diào)用時(shí)傳入妇押。


-最后附上一個(gè)手寫(xiě)實(shí)現(xiàn)call()函數(shù):

Function.prototype.myCall = function(thisArg, ...args) {
    const fn = Symbol('fn')        // 聲明一個(gè)獨(dú)有的Symbol屬性, 防止fn覆蓋已有屬性
    thisArg = thisArg || window    // 若沒(méi)有傳入this, 默認(rèn)綁定window對(duì)象
    thisArg[fn] = this              // this指向調(diào)用call的對(duì)象,即我們要改變this指向的函數(shù)
    const result = thisArg[fn](...args)  // 執(zhí)行當(dāng)前函數(shù)
    delete thisArg[fn]              // 刪除我們聲明的fn屬性
    return result                  // 返回函數(shù)執(zhí)行結(jié)果
}

引自:https://juejin.im/post/6844904116552990727

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末跷究,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子敲霍,更是在濱河造成了極大的恐慌俊马,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肩杈,死亡現(xiàn)場(chǎng)離奇詭異柴我,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)扩然,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)艘儒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人夫偶,你說(shuō)我怎么就攤上這事界睁。” “怎么了兵拢?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵翻斟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我说铃,道長(zhǎng)访惜,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任腻扇,我火速辦了婚禮债热,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衙解。我一直安慰自己阳柔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布蚓峦。 她就那樣靜靜地躺著舌剂,像睡著了一般济锄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上霍转,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天荐绝,我揣著相機(jī)與錄音,去河邊找鬼避消。 笑死低滩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的岩喷。 我是一名探鬼主播恕沫,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纱意!你這毒婦竟也來(lái)了婶溯?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤偷霉,失蹤者是張志新(化名)和其女友劉穎迄委,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體类少,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叙身,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了硫狞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片信轿。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖残吩,靈堂內(nèi)的尸體忽然破棺而出虏两,到底是詐尸還是另有隱情,我是刑警寧澤世剖,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站笤虫,受9級(jí)特大地震影響旁瘫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜琼蚯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一酬凳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧遭庶,春花似錦宁仔、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)权埠。三九已至,卻和暖如春煎谍,著一層夾襖步出監(jiān)牢的瞬間攘蔽,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工呐粘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留满俗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓作岖,卻偏偏與公主長(zhǎng)得像唆垃,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痘儡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361