從一道前端筆試題分析javascript中this的使用陷阱

相信大家都有看過(guò)這樣的一道javascript的面試題雾叭,具體如下:

var length = 10;
function fn(){
  console.log(this.length);
}
var obj = {
    length:5,
    method:function(fn){
      fn();
      arguments[0]();
    }
}
obj.method(fn,1);

這道題主要考察的是this的指向和arguments對(duì)象悟耘,第二個(gè)輸出為2,這里我們不討論這個(gè)話題织狐。第一個(gè)輸出的如果對(duì)this理解模糊的話容易答出5的答案暂幼,其實(shí)答案為10。


分析:javascript判斷this綁定的判定規(guī)則是調(diào)用位置是否有上下文對(duì)象移迫,或者說(shuō)是否被某個(gè)對(duì)象擁有或者包含旺嬉,先思考如下代碼:

function fn(){
  console.log(this.a);
}  
var obj = {
  a:2,
  fn:fn
}
obj.fn(); //2

首先需要注意的是fn()的聲明方式,及其之后是如何被當(dāng)作引用屬性添加到obj中的厨埋。但是無(wú)論是直接在obj定義還是先定義再添加為引用屬性邪媳,這個(gè)函數(shù)嚴(yán)格來(lái)說(shuō)都不屬于obj對(duì)象。
然而荡陷,調(diào)用位置會(huì)使用obj的上下文來(lái)引用函數(shù)雨效,因此你可以說(shuō)函數(shù)被調(diào)用時(shí)obj對(duì)象“擁有”或者“包含”它。
無(wú)論你如何稱呼這個(gè)模式废赞,但fn()被調(diào)用時(shí)徽龟,它的前面確實(shí)加上了對(duì)obj的引用。當(dāng)函數(shù)引用有上下文對(duì)象時(shí)唉地,函數(shù)調(diào)用中的this會(huì)綁定到這個(gè)上下文對(duì)象据悔。因此調(diào)用fn()時(shí)this被綁定到obj,因此this.a和obj.a時(shí)一樣的耘沼。

一種最常見(jiàn)的this綁定問(wèn)題就是被隱式綁定的函數(shù)會(huì)丟失綁定對(duì)象极颓,也就是說(shuō)它會(huì)應(yīng)用默認(rèn)綁定,從而把this綁定到全局對(duì)象或者undefined上群嗤。

思考下面的代碼:

function fn(){
  console.log(this.a);
}
var obj = {
  a:2,
  fn:fn
}
var bar = obj.fn; //函數(shù)別名
bar();//undefined

雖然bar是obj.fn的一個(gè)引用菠隆,但是實(shí)際上,它引用的是fn函數(shù)本身,因此此時(shí)的bar()其實(shí)是一個(gè)不帶任何修飾的函數(shù)調(diào)用浸赫,因此為undefined闰围。

回到之前的筆試題,參數(shù)傳遞其實(shí)就是一種隱式的賦值既峡,下面的例子的參數(shù)傳遞和上面例子的 var bar = obj.fn其實(shí)是一樣的羡榴。所以答案為10。

var length = 10;
function fn(){
  console.log(this.length);
}
var obj = {
    length:5,
    method:function(fn){//fn其實(shí)引用的是function fn()
      fn();//這里才是真正的調(diào)用位置
      arguments[0]();
    }
}
obj.method(fn,1);

那如果把函數(shù)傳入到語(yǔ)言內(nèi)置的函數(shù)而不是傳入你自己聲明的函數(shù)运敢,會(huì)發(fā)生什么呢校仑?結(jié)果是一樣的,沒(méi)有區(qū)別:

function fn(){
  console.log(this.a);
}  
var obj = {
  a:2,
  fn:fn
}
var a = "global";
setTimeout(obj.fn,100);

javascript環(huán)境中內(nèi)置的setTimeout()函數(shù)的實(shí)現(xiàn)和下面的偽代碼類似:

function setTimeout(fn,delay){
  //等待delay毫秒
  fn();//調(diào)用位置
}

就像我們看到的那樣传惠,回調(diào)函數(shù)丟失this綁定是很常見(jiàn)的迄沫。除此之外,還有一種情況this的行為出乎我們的意料:調(diào)用回調(diào)函數(shù)的函數(shù)可能會(huì)修改this卦方。在一些流行的javascript框架中的事件處理器常會(huì)把回調(diào)函數(shù)的this強(qiáng)制綁定到觸發(fā)事件的dom元素上羊瘩。最后來(lái)一道測(cè)試題:

function fn(){
  console.log(this.a);
}
var a = 2;
var o = { a:3,fn:fn};
var p = { a:4}
o.fn();//輸出?
(p.fn = o.fn)();//輸出盼砍?

答案:3和2尘吗。

最后,分享下分析這種隱式綁定的原則:如果在一個(gè)對(duì)象內(nèi)包含一個(gè)指向函數(shù)的屬性浇坐,并通過(guò)這個(gè)屬性間接引用函數(shù)睬捶,只有在這種情況下的this才會(huì)綁定到這個(gè)對(duì)象上。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末近刘,一起剝皮案震驚了整個(gè)濱河市擒贸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌觉渴,老刑警劉巖介劫,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異疆拘,居然都是意外死亡蜕猫,警方通過(guò)查閱死者的電腦和手機(jī)寂曹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門哎迄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人隆圆,你說(shuō)我怎么就攤上這事漱挚。” “怎么了渺氧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵旨涝,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我侣背,道長(zhǎng)白华,這世上最難降的妖魔是什么慨默? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮弧腥,結(jié)果婚禮上厦取,老公的妹妹穿的比我還像新娘。我一直安慰自己管搪,他們只是感情好虾攻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著更鲁,像睡著了一般霎箍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上澡为,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天漂坏,我揣著相機(jī)與錄音,去河邊找鬼媒至。 笑死樊拓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的塘慕。 我是一名探鬼主播筋夏,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼图呢!你這毒婦竟也來(lái)了条篷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蛤织,失蹤者是張志新(化名)和其女友劉穎赴叹,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體指蚜,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乞巧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摊鸡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绽媒。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖免猾,靈堂內(nèi)的尸體忽然破棺而出是辕,到底是詐尸還是另有隱情,我是刑警寧澤猎提,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布获三,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏疙教。R本人自食惡果不足惜棺聊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贞谓。 院中可真熱鬧躺屁,春花似錦、人聲如沸经宏。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)烁兰。三九已至耐亏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沪斟,已是汗流浹背广辰。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留主之,地道東北人择吊。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像槽奕,于是被迫代替她去往敵國(guó)和親几睛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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

  • 1.函數(shù)調(diào)用棧和調(diào)用位置 在函數(shù)執(zhí)行的時(shí)候粤攒,會(huì)有一個(gè)活動(dòng)記錄(也叫執(zhí)行上下文)來(lái)記錄函數(shù)的調(diào)用順序所森,這個(gè)就是函數(shù)調(diào)...
    lightNate閱讀 525評(píng)論 1 14
  • this是JavaScript中最復(fù)雜的機(jī)制之一,被自動(dòng)定義在所有函數(shù)的作用域中夯接』兰茫“When a function...
    GeniusFunny閱讀 783評(píng)論 0 5
  • 淺談javascript中this的指向 調(diào)用位置 在理解this的綁定過(guò)程之前,首先要理解調(diào)用位置盔几。調(diào)用位置就是...
    蒹葭de閱讀 283評(píng)論 0 1
  • 在翻閱《你不知道的javascript》這一套書(shū)的中上卷目錄之后晴弃,發(fā)現(xiàn)書(shū)中針對(duì)閉包、對(duì)象逊拍、原型上鞠、語(yǔ)法、異步顺献、回調(diào)等...
    夜來(lái)小星閱讀 249評(píng)論 0 0
  • 這個(gè)世界上總有那么20%的人旗国,見(jiàn)到你就是莫名其妙的喜歡你枯怖,總有那么20%的人注整,見(jiàn)到你就是莫名其妙的討厭你,剩余的6...
    管文寧閱讀 116評(píng)論 0 0