JavaScript學(xué)習(xí)-this

this是什么

  • 有兩種常見(jiàn)的對(duì)this的錯(cuò)誤理解:
    1.this指向函數(shù)自身
    2.this指向的是作用域
  • 正確的理解
    當(dāng)一個(gè)函數(shù)被調(diào)用時(shí)级解,會(huì)創(chuàng)建一個(gè)活動(dòng)記錄(有時(shí)候也稱(chēng)為執(zhí)行上下文)喊积。這個(gè)記錄會(huì)包含函數(shù)在哪里被調(diào)用(調(diào)用棧)殖告、函數(shù)的調(diào)用方式吃溅、傳入的參數(shù)等信息风罩。this 就是這個(gè)記錄的一個(gè)屬性陨亡,會(huì)在函數(shù)執(zhí)行的過(guò)程中用到岁忘。
    簡(jiǎn)單來(lái)說(shuō)辛慰,this 的綁定和函數(shù)聲明的位置沒(méi)有任何關(guān)系,只取決于函數(shù)的調(diào)用方式干像。

綁定規(guī)則

1.默認(rèn)綁定(嚴(yán)格模式/非嚴(yán)格模式)

獨(dú)立函數(shù)調(diào)用帅腌,this指向全局對(duì)象。嚴(yán)格模式下蝠筑,不能講全局對(duì)象用于默認(rèn)綁定狞膘,this會(huì)綁定到undefined揩懒。在嚴(yán)格模式下調(diào)用函數(shù)則不影響默認(rèn)綁定什乙。

function foo() { // 運(yùn)行在嚴(yán)格模式下,this會(huì)綁定到undefined
    "use strict";
    console.log( this.a );
}

var a = 2;

// 調(diào)用
foo(); // TypeError: Cannot read property 'a' of undefined

function foo() { // 運(yùn)行
    console.log( this.a );
}

var a = 2;

(function() { // 嚴(yán)格模式下調(diào)用函數(shù)則不影響默認(rèn)綁定
    "use strict";
    foo(); // 2
})();

2.隱式綁定

當(dāng)函數(shù)引用有上下文對(duì)象時(shí)已球,隱式綁定規(guī)則會(huì)把函數(shù)中的this綁定到這個(gè)上下文對(duì)象臣镣。對(duì)象屬性引用鏈中只有上一層或者說(shuō)最后一層在調(diào)用中起作用。

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

var obj2 = { 
 a: 42, 
 foo: foo 
}; 

var obj1 = { 
 a: 2, 
 obj2: obj2 
}; 

obj1.obj2.foo(); // 42

隱式綁定的函數(shù)在特定情況下會(huì)丟失綁定對(duì)象智亮,應(yīng)用到默認(rèn)綁定中

// 雖然bar是obj.foo的一個(gè)引用忆某,但是實(shí)際上,它引用的是foo函數(shù)本身阔蛉。
// bar()是一個(gè)不帶任何修飾的函數(shù)調(diào)用弃舒,應(yīng)用默認(rèn)綁定。
function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

var bar = obj.foo; // 函數(shù)別名

var a = "oops, global"; // a是全局對(duì)象的屬性

bar(); // "oops, global"

參數(shù)傳遞也是一種隱式賦值

3.顯式綁定

通過(guò)call(),apply()方法改變this的指向状原。
但是顯式綁定仍然無(wú)法解決綁定丟失的問(wèn)題聋呢。
解決綁定丟失的問(wèn)題:

  • 硬綁定
    創(chuàng)建了函數(shù) bar(),并在它的內(nèi)部手動(dòng)調(diào)用 foo.call(obj)颠区,因此強(qiáng)制把 foo 的 this 綁定到了 obj削锰。無(wú)論之后如何調(diào)用函數(shù) bar,它總會(huì)手動(dòng)在 obj 上調(diào)用 foo毕莱。這種綁定是一種顯式的強(qiáng)制綁定器贩,因此我們稱(chēng)之為硬綁定颅夺。
  • api調(diào)用的上下文
    JS許多內(nèi)置函數(shù)提供了一個(gè)可選參數(shù),被稱(chēng)之為“上下文”(context)蛹稍,其作用和bind(..)一樣吧黄,確保回調(diào)函數(shù)使用指定的this唆姐。這些函數(shù)實(shí)際上通過(guò)call(..)和apply(..)實(shí)現(xiàn)了顯式綁定稚字。

4.new綁定

使用new來(lái)調(diào)用函數(shù),或者說(shuō)發(fā)生構(gòu)造函數(shù)調(diào)用時(shí)厦酬,會(huì)自動(dòng)執(zhí)行下面的操作胆描。

  • 1.創(chuàng)建(或者說(shuō)構(gòu)造)一個(gè)新對(duì)象。
  • 2.這個(gè)新對(duì)象會(huì)被執(zhí)行[[Prototype]]連接仗阅。
  • 3.這個(gè)新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this昌讲。
  • 4.如果函數(shù)沒(méi)有返回其他對(duì)象,那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對(duì)象减噪。

使用new來(lái)調(diào)用foo(..)時(shí)短绸,會(huì)構(gòu)造一個(gè)新對(duì)象并把它(bar)綁定到foo(..)調(diào)用中的this。

function foo(a) { 
this.a = a; 
} 
var bar = new foo(2); 
console.log( bar.a ); //  2

手寫(xiě)一個(gè)new的實(shí)現(xiàn)
實(shí)現(xiàn)new的4步操作

function _new(fn, ...args) {
      //先用Object創(chuàng)建一個(gè)空的對(duì)象,
      const obj = {}    
      //將空對(duì)象掛到fn的原型鏈上
      obj.__proto__ = fn.prototype
      //改變this指向 
      const rel = fn.apply(obj, args)
      //返回
      return rel instanceof Object ? rel : obj
    }

優(yōu)先級(jí)

new > 顯式綁定 > 隱式綁定 > 默認(rèn)綁定

備注

ES6 中的箭頭函數(shù)并不會(huì)使用四條標(biāo)準(zhǔn)的綁定規(guī)則筹裕,而是根據(jù)當(dāng)前的詞法作用域來(lái)決定this醋闭,具體來(lái)說(shuō),箭頭函數(shù)會(huì)繼承外層函數(shù)調(diào)用的 this 綁定(無(wú)論 this 綁定到什么)朝卒。這其實(shí)和 ES6 之前代碼中的 self = this 機(jī)制一樣证逻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市抗斤,隨后出現(xiàn)的幾起案子囚企,更是在濱河造成了極大的恐慌,老刑警劉巖瑞眼,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龙宏,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡伤疙,警方通過(guò)查閱死者的電腦和手機(jī)银酗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)徒像,“玉大人黍特,你說(shuō)我怎么就攤上這事〕Γ” “怎么了衅澈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)谬墙。 經(jīng)常有香客問(wèn)我今布,道長(zhǎng)经备,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任部默,我火速辦了婚禮侵蒙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘傅蹂。我一直安慰自己纷闺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布份蝴。 她就那樣靜靜地躺著犁功,像睡著了一般。 火紅的嫁衣襯著肌膚如雪婚夫。 梳的紋絲不亂的頭發(fā)上浸卦,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音案糙,去河邊找鬼限嫌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛时捌,可吹牛的內(nèi)容都是我干的怒医。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼奢讨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼稚叹!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起禽笑,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤入录,失蹤者是張志新(化名)和其女友劉穎蛤奥,沒(méi)想到半個(gè)月后佳镜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凡桥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年蟀伸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缅刽。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡啊掏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衰猛,到底是詐尸還是另有隱情迟蜜,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布啡省,位于F島的核電站娜睛,受9級(jí)特大地震影響髓霞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜畦戒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一方库、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧障斋,春花似錦纵潦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至遂庄,卻和暖如春被济,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背涧团。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工只磷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泌绣。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓钮追,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親阿迈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子元媚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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