#JS續(xù):3.0 this的前置了解

前言

了解this之前我們看看這篇文章:
[譯]讓我們一起解決“this”難題第一部分

真的看完之后無數(shù)次都嘖嘖稱奇葛碧,老外的文章看得太爽了吧萎河。這里我只截取部分我認為重要的知識來記錄我對this的理解金砍,部分表述有出入忘苛。

以下對this的理解浦徊,默認你已經(jīng)了解一些JavaScript的背景知識媒楼,講到global、window雳刺、this劫灶、prototype等等時,你知道它們是什么意思掖桦。雖然文章中默認所使用global和window本昏,在這里是同一回事,可以互換滞详。實際上我查了資料凛俱,其實是不一樣的紊馏,簡要說明一下:(不過不要過于糾結(jié))

global: 全局對象global是在全局上下文中的變量對象料饥,是一個不依賴宿主環(huán)境的對象,(注:常見的宿主環(huán)境:瀏覽器和nodejs)一切全局里存在的變量和函數(shù)都是它的屬性和方法朱监。global 不能直接被訪問而是間接訪問岸啡,訪問其屬性。如Math赫编、String等等都可以看作是全局對象 global的屬性巡蘸,對global的屬性的訪問往往省略掉前綴,比如Math.abs(1)其實就是[[global]].Math.abs(1)

window:‘usestrict’模式下擂送,我們更強調(diào)window的全局對象的作用(除此之外悦荒,則常用global作為全局對象)。window對象是相對于Web瀏覽器而言的嘹吨,它并不是ECMAScript規(guī)定的內(nèi)置對象搬味,它是瀏覽器的WebAPI,是存在于瀏覽器之中的蟀拷,也就是離開瀏覽器這個宿主環(huán)境的話就不存在此對象了碰纬。所以,Global對象是包含于window對象這種情況的開始

一问芬、this的第1條規(guī)則:默認綁定

默認綁定規(guī)則規(guī)定悦析,當一個函數(shù)執(zhí)行獨立調(diào)用時,例如只是funcName();此衅,這時函數(shù)的“this”被指向 global 對象强戴。這里要注意的是亭螟,嚴格模式下,全局對象是不會默認綁定的酌泰,因此如果你在開啟了嚴格模式媒佣,那么控制臺輸出的就是 undefined,而不再是全局變量陵刹。
先看下面這個代碼:

//例子1
function foo() {
 function bar() {
  console.log(this); 
 } 
 bar();
}

foo();

foo 先被調(diào)用默伍,然后又調(diào)用bar,bar將“this”打印到控制臺中衰琐。這里的技巧是看看函數(shù)是如何被調(diào)用的:foo和bar都被單獨調(diào)用也糊,因此,他們內(nèi)部的“this”都是指向 global 對象羡宙。但是由于 bar 是唯一執(zhí)行打印的函數(shù)狸剃,所以我們看到 global 對象在控制臺中輸出了一次。

再看一下面的代碼:

//例子2
var a = 1;

function foo() {  
 console.log(this.a);  
}

foo();
//1

輸出結(jié)果是 undefined狗热?是 1钞馁?還是什么?
如果你已經(jīng)很好地理解了之前講解的內(nèi)容匿刮,那么你應該知道控制臺輸出的是“1”僧凰。為什么?首先熟丸,默認綁定作用于函數(shù) foo训措。因此 foo 中的“this”指向 global 對象,并且 a 被聲明為 global 變量光羞,這就意味著 a 是 global 對象的屬性(也稱之為全局對象污染)绩鸣,因此this.avar a就是同一個東西。

二纱兑、this的第2條規(guī)則:隱式綁定呀闻。

隱式綁定規(guī)則規(guī)定,當一個函數(shù)被作為一個對象方法被調(diào)用時潜慎,那么它內(nèi)部的“this”應該指向這個對象捡多。
先看下面這個代碼:

//例子3
var obj = {  
 a: 1,   
 foo: function() {  
  console.log(this);   
 }  
};

obj.foo();

如果函數(shù)調(diào)用前面有多個對象(obj1.obj2.func()),那么函數(shù)之前的最后一個對象(obj3)會被綁定勘纯。

需要注意的一點是局服,函數(shù)調(diào)用必須有效,那也就是說當你調(diào)用obj.func()時驳遵,必須確保 func 是對象 obj 的屬性淫奔。

因此,在上面的例子中調(diào)用obj.foo()時堤结,“this”就指向 obj唆迁,因此 obj 被打印輸出在控制臺中鸭丛。

三、進階:默認綁定和隱性綁定兩種規(guī)則結(jié)合

【重要】
我們必須知道唐责,this在調(diào)用一個函數(shù)函數(shù)前鳞溉,并沒有綁定在這個函數(shù),
判斷運用了那種綁定規(guī)則鼠哥,要密切注意這個函數(shù)是如何是否被單獨調(diào)用熟菲。
如果單獨調(diào)用的話,就是默認綁定朴恳,函數(shù)的“this”都指向全局對象global抄罕;如果是對象屬性的調(diào)用,那么就是隱性綁定于颖。

1呆贿、先看以下代碼:

//例子4
function logThis() {  
 console.log(this);  
}

var myObject = {  
 a: 1,   
 logThis: logThis  
};

logThis();  
myObject.logThis();

跟在 myObject 后面的這個全局調(diào)用logThis()單獨被調(diào)用的時候,通過 console.log(this)打印的是global對象森渐;而myObject.logThis()做入,此時logThis()就是作為函數(shù)的屬性進行調(diào)用的, 打印是 myObject 對象同衣。

2竟块、一個有趣的現(xiàn)象:

console.log(logThis === myObject.logThis); // true

為什么不呢?它們當然是相同的函數(shù)乳怎,但是你可以看到 如何調(diào)用_logThis_ 會讓其中的“this”發(fā)生改變彩郊。當logThis被單獨調(diào)用時前弯,使用默認綁定規(guī)則蚪缀,但是當 logThis 作為前面的對象屬性被調(diào)用時,使用隱式綁定規(guī)則恕出。

四询枚、繼續(xù)探討this的運用

1、先看這個例子:

//例子5
function foo() {  
 var a = 2;  
 this.bar();  
}

function bar() {  
 console.log(this.a);  
}

foo();
//undefined

就像例子2 的 var a一樣浙巫,bar也是全局對象的屬性金蜀。因為foo被單獨調(diào)用了,它內(nèi)部的“this”就是全局對象(默認綁定)的畴。因此 foo 內(nèi)部的 this.bar 就是 bar渊抄。控制臺中輸出什么丧裁?如果你猜的沒錯护桦,“undefined”會被打印出來。

注意 bar 是如何被調(diào)用的煎娇?看起來二庵,隱式綁定在這里發(fā)揮作用贪染。隱式綁定意味著 bar 中的“this”是其前面的對象引用。bar前面的對象引用是全局對象催享,在 foo 里面是全局對象杭隙,對不對?因此在 bar 中嘗試訪問 this.a等同于訪問 [global object].a因妙。而全局對象沒有屬性a痰憎,沒有什么意外的話,控制臺會輸出 undefined攀涵。

2信殊、再看一下下面例子:

//例子6
var obj = {  
 a: 1,   
 foo: function(fn) {  
  console.log(this);  
  fn();  
 }  
};

obj.foo(function() {  
 console.log(this);  
});

//{a: 1, foo: ?}
//window

是不是瞬間看不懂這個代碼是什么呢?不要著急汁果,把它簡化一下吧涡拘,把
obj.foo(function() { console.log(this); });簡化成 obj.foo();
這樣看來,函數(shù)foo是接受一個回調(diào)函數(shù)作為參數(shù)据德。我們所做的就是在調(diào)用foo的時候在參數(shù)里面放了一個函數(shù)鳄乏。
obj.foo( function() { console.log(this); } );
foo 是 如何 被調(diào)用的?它是一個單獨調(diào)用嗎棘利?當然不是橱野,因此第一個輸出到控制臺的是對象 obj 。我們傳入的回調(diào)函數(shù)是什么善玫?在 foo 內(nèi)部水援,回調(diào)函數(shù)變?yōu)?fn 。那么 fn 是 如何被調(diào)用茅郎?fn中的“this”是指向全局對象蜗元,因此第二個被輸出到控制臺的是全局對象。

3系冗、看一個和構(gòu)造函數(shù)相關(guān)的例子:

//例子7
var arr = [1, 2, 3, 4];

Array.prototype.myCustomFunc = function() {
 console.log(this);
};

arr.myCustomFunc();
//[1, 2, 3, 4]

是不是又傻眼了奕扣?如果對于原型不是很熟悉,就把它當做一個普通的對象掌敬,然后一個執(zhí)行this的函數(shù)賦值給它惯豆,然后調(diào)用myCustomFunc時,就是調(diào)用這個函數(shù)對象奔害,此刻發(fā)揮了隱性綁定的作用(我們始終不要忘記兩種綁定規(guī)則的判定標準)楷兽,此時函數(shù)內(nèi)部的this就是指向myCustomFunc這個對象,arr調(diào)用之后华临,輸出結(jié)果就是:[1, 2, 3, 4]

4芯杀、再看一下下面的例子:

//例子8

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

obj.foo();

var bar = obj.foo;  
bar();

不要被這里面的花哨代碼所分心,只需注意函數(shù)是如何被調(diào)用的,就可以弄明白“this”的含義瘪匿。你現(xiàn)在一定已經(jīng)掌握這個技巧了吧跛梗。首先obj.foo()被調(diào)用,因為 foo 前面有一個對象引用棋弥,所以首先輸出的是對象obj核偿。bar當然是被獨立調(diào)用的,因此下一個輸出是全局變量顽染。這里要注意的是漾岳,bar和foo是對同一個函數(shù)的引用,唯一區(qū)別是它們被調(diào)用的方式不同粉寞。

做到這里我已經(jīng)夠理解this(其實是時間不夠)尼荆。其實還有幾個例子,我全看完了唧垦,自己做了之后全對捅儒,希望看到這篇的你也能學會this的指向。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末振亮,一起剝皮案震驚了整個濱河市巧还,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坊秸,老刑警劉巖麸祷,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異褒搔,居然都是意外死亡阶牍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門星瘾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來走孽,“玉大人,你說我怎么就攤上這事死相∪谇螅” “怎么了咬像?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵算撮,是天一觀的道長。 經(jīng)常有香客問我县昂,道長肮柜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任倒彰,我火速辦了婚禮审洞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己芒澜,他們只是感情好仰剿,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著痴晦,像睡著了一般南吮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上誊酌,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天部凑,我揣著相機與錄音,去河邊找鬼碧浊。 笑死涂邀,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的箱锐。 我是一名探鬼主播比勉,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼驹止!你這毒婦竟也來了敷搪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤幢哨,失蹤者是張志新(化名)和其女友劉穎赡勘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捞镰,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡闸与,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了岸售。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片践樱。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖凸丸,靈堂內(nèi)的尸體忽然破棺而出拷邢,到底是詐尸還是另有隱情,我是刑警寧澤屎慢,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布瞭稼,位于F島的核電站,受9級特大地震影響腻惠,放射性物質(zhì)發(fā)生泄漏环肘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一集灌、第九天 我趴在偏房一處隱蔽的房頂上張望悔雹。 院中可真熱鬧,春花似錦、人聲如沸腌零。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽益涧。三九已至初肉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饰躲,已是汗流浹背牙咏。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嘹裂,地道東北人妄壶。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像寄狼,于是被迫代替她去往敵國和親丁寄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

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

  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點點福利:阿里云產(chǎn)品券删咱,享受所有官網(wǎng)優(yōu)惠屑埋,并抽取幸運大...
    HetfieldJoe閱讀 6,926評論 15 54
  • 一瘦穆、你不知道的JavaScript 1烛愧、作用域 作用域 LHS RHS RHS查詢與簡單地查找某個變量的值別無二...
    頂兒響叮當閱讀 346評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)另伍,斷路器敲街,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • 因為關(guān)注貓叔的公眾號团搞,無意間加入了長投的21天理財訓練營,抱著支持貓叔體驗一下的心態(tài)報名加入了學習群并堅持...
    小城青年92閱讀 564評論 1 2
  • 【05/09/2017 周二 丁酉年 四月十四】 ?靜√智√勇√仁√強√禮 小結(jié): 早上看《摩法多一家親》之④《摩...
    媽媽熊閱讀 223評論 0 2