關于非箭頭函數中this指向哪個對象的問題

回家的路上膳灶,我試圖忘掉瑪利亞·塞克斯咱士,當我爸跟我說晚安的時候--他每次喝完一瓶啤酒就會醉過去,可今天他喝了兩瓶(驚嘆!)--我試著忘記瑪利亞·塞克斯序厉。半小時以后锐膜,伊奇來到我的房里,剛洗完淋浴脂矫,散發(fā)著清新的味道枣耀,穿著破爛的“探險家朵拉”睡衣,給我臉頰上來了一個邋遢的濕吻庭再,我試著忘記她捞奕;一個小時之后,我媽來到房間門外拄轻,說:“我真為你驕傲颅围,薩姆『薮辏”這時院促,我還在想著她。 --《忽然七日》

每個函數內部都有兩個特殊的對象斧抱,分別是arguments對象和this對象常拓。對于arguments對象,我們知道他是一個類數組辉浦,里面的項是傳遞進來的參數弄抬;還需要注意的地方是它還具有一個callee屬性,arguments.callee屬性的值就是函數本身宪郊。同時每個函數都包含有下面三個屬性:length掂恕,prototype,caller弛槐。length屬性表明函數所期望接收的參數個數懊亡;prototype屬性就不解釋了;caller屬性的值是調用該函數的那個函數的一個引用乎串。

而我們今天要談的就是函數內部的一個特殊的對象——this店枣。this引用的是函數據以執(zhí)行的環(huán)境對象,對于非箭頭函數來說:具體指向哪個對象取決于函數調用時所處的環(huán)境叹誉,而不是函數被聲明時的那個環(huán)境艰争;但是對于的箭頭函數的情況便是和此相反:具體指向哪個對象取決于函數被聲明時所處的那個環(huán)境,而不是被調用時所處的環(huán)境桂对。

分析普通函數的調用情況甩卓,大致可以分為下面幾種:

  • 1.作為對象的方法調用;
  • 2.作為普通函數被調用蕉斜;
  • 3.作為構造器函數被調用逾柿;
  • 4.被某些能夠延長作用域鏈的函數間接調用缀棍,比如Function.prototype.call和Function.prototype.bind函數。

這里既然提到了Function.prototype.apply()机错,Function.prototype.call()的話爬范,那就打個岔吧,在加入Function.prototype.bind()弱匪,下面捋一捋他們的區(qū)別青瀑。

首先,三個函數都能夠改變函數所處的環(huán)境對象萧诫。其中apply()和call()是改變后立馬執(zhí)行的斥难,這兩者之間的區(qū)別是apply()能夠接收數組以及類數組對象作為第二個參數以便傳入多個參數;而call()就不行帘饶,他必須顯式的把每一個參數分別作為call的第二參數哑诊,第三參數依次傳遞過去。而對于bind函數來說及刻,這個方法會創(chuàng)建一個函數的實例镀裤,他的this值會被綁定到那個傳入的參數上。和前兩者的關鍵區(qū)別在于缴饭,他不執(zhí)行暑劝。需要注意的地方是:如果我們對上面三個函數傳入的環(huán)境對象是null或者undefined的話,那么函數的實際執(zhí)行環(huán)境將會是全局執(zhí)行環(huán)境颗搂,在瀏覽器中就是window铃岔,在node環(huán)境里就是global。下面可以舉個例子看一下:

var a = 999;
function fun(){console.log(this.a);}
fun.apply(null);//9

言歸正傳峭火,下面來討論一下在不同的調用函數的方式下this指向哪個對象的分析方法:

  • 1.當作為對象方法被調用時,this指向該對象智嚷;
  • 2.當作為普通函數調用時卖丸,this總是指向全局對象。這一點是很讓人迷惑的盏道,看看下面的這個例子:
var a = 999;
var obj = {"a" : 111, "fun": function(){
  console.log(this.a);
  var test = function(){console.log(this.a);
  test();
}};
obj.fun();//111/n999

可以很明顯的看到稍浆,我們的fun()被調用是返回的是999,說明他的執(zhí)行環(huán)境是全局環(huán)境猜嘱。對于這種情況衅枫,有的時候的確是會給我們帶來挺多不必要的麻煩,比如說下面這個例子:

window.id = "window";
var callback = function(){
  console.log(this.id);
};
document.getElementById("div1").onclick = function(){
  console.log(this.id);//"div1"
  callback();//"window"
}

對于這個callback而言朗伶,我們最初是希望它的環(huán)境對象是div1的DOM對象的弦撩,然而實際上卻被綁定到了全局對象window上,而這并不是我們所希望的论皆。當然益楼,這樣做也是具有解決辦法的猾漫,像下面這樣。

window.id = "window";
document.getElementById("div1").onclick = function(){
  var that = this;
  console.log(this.id);//"div1"
  var callback = function(){console.log(that.id);};
  callback();//"div1"
}

或者通過call和apply后者bind來改變環(huán)境對象感凤。

window.id = "window";
var callback = function(){
  console.log(this.id);
};
document.getElementById("div1").onclick = function(){
  console.log(this.id);//"div1"
  callback.apply(this);//"div1"
}
  • 3.作為構造器函數調用:凡是正常的構造器函數悯周,他們之中的this都是引用著構造器所返回的對象的。
  • 4.當函數利用apply()或者call()以及bind()改變環(huán)境對象時陪竿,函數的環(huán)境對象為這三個方法所傳入的那第一個參數對象禽翼。

拓展:思考下面這樣這樣會不會出錯

var getId = document.getElementById;
getId("someID");

答案是會出錯的。首先族跛,需要明確的是:函數的名字僅僅是一個包含指針的變量而已闰挡。因此,即使在不同的環(huán)境中執(zhí)行庸蔼,他們所指向的都是同一個函數解总。因此,我們的document.getElementById和getId都是指向同一個函數的姐仅,不同的時他們所指向的環(huán)境對象的不同花枫,對于前者來說他的環(huán)境對象時document而后者的環(huán)境對象確實window。而對于該函數的內部實現機理來說掏膏,我們時必須要求為document的劳翰,所以調用getID的話會出錯。

我們活著的每一刻背后都隱藏著成千上萬個不一樣的瞬間馒疹。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末佳簸,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子颖变,更是在濱河造成了極大的恐慌生均,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腥刹,死亡現場離奇詭異马胧,居然都是意外死亡,警方通過查閱死者的電腦和手機衔峰,發(fā)現死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門佩脊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人垫卤,你說我怎么就攤上這事威彰。” “怎么了穴肘?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵歇盼,是天一觀的道長。 經常有香客問我评抚,道長旺遮,這世上最難降的妖魔是什么赵讯? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮耿眉,結果婚禮上边翼,老公的妹妹穿的比我還像新娘。我一直安慰自己鸣剪,他們只是感情好组底,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著筐骇,像睡著了一般债鸡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铛纬,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天厌均,我揣著相機與錄音,去河邊找鬼告唆。 笑死棺弊,一個胖子當著我的面吹牛,可吹牛的內容都是我干的擒悬。 我是一名探鬼主播模她,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼懂牧!你這毒婦竟也來了侈净?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤僧凤,失蹤者是張志新(化名)和其女友劉穎畜侦,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體躯保,經...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡旋膳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了吻氧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡咏连,死狀恐怖盯孙,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情祟滴,我是刑警寧澤振惰,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站垄懂,受9級特大地震影響骑晶,放射性物質發(fā)生泄漏痛垛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一桶蛔、第九天 我趴在偏房一處隱蔽的房頂上張望匙头。 院中可真熱鬧,春花似錦仔雷、人聲如沸蹂析。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽电抚。三九已至,卻和暖如春竖共,著一層夾襖步出監(jiān)牢的瞬間蝙叛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工公给, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留借帘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓妓布,卻偏偏與公主長得像姻蚓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子匣沼,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內容