this 指向詳細(xì)解析(箭頭函數(shù))

本文地址:http://www.cnblogs.com/dongcanliang/p/7054176.html

前言

this 指向問題是入坑前端必須了解知識(shí)點(diǎn)拆讯,現(xiàn)在迎來了ES6時(shí)代养葵,因?yàn)榧^函數(shù)的出現(xiàn)撮竿,所以感覺有必要對(duì) this 問題梳理一下尘喝,遂有此文

在非箭頭函數(shù)下啸蜜, this 指向調(diào)用其所在函數(shù)的對(duì)象杯聚,而且是離誰近就是指向誰(此對(duì)于常規(guī)對(duì)象烛芬,原型鏈辆童, getter & setter等都適用)宜咒;構(gòu)造函數(shù)下,this與被創(chuàng)建的新對(duì)象綁定把鉴;DOM事件故黑,this指向觸發(fā)事件的元素;內(nèi)聯(lián)事件分兩種情況庭砍,bind綁定场晶, call & apply 方法等, 容以下一步一步討論怠缸。箭頭函數(shù)也會(huì)穿插其中進(jìn)行討論诗轻。

全局環(huán)境下

在全局環(huán)境下,this 始終指向全局對(duì)象(window), 無論是否嚴(yán)格模式揭北;

console.log(this.document ===document);// true// 在瀏覽器中扳炬,全局對(duì)象為 window 對(duì)象:console.log(this===window);// truethis.a =37;console.log(window.a);// 37

函數(shù)上下文調(diào)用

函數(shù)直接調(diào)用

普通函數(shù)內(nèi)部的this分兩種情況,嚴(yán)格模式和非嚴(yán)格模式搔体。

非嚴(yán)格模式下恨樟,this 默認(rèn)指向全局對(duì)象window

functionf1(){returnthis;}f1() ===window;// true

而嚴(yán)格模式下, this為undefined

functionf2(){? "use strict";// 這里是嚴(yán)格模式returnthis;}f2() ===undefined;// true

對(duì)象中的this

對(duì)象內(nèi)部方法的this指向調(diào)用這些方法的對(duì)象疚俱,

函數(shù)的定義位置不影響其this指向劝术,this指向只和調(diào)用函數(shù)的對(duì)象有關(guān)。

多層嵌套的對(duì)象呆奕,內(nèi)部方法的this指向離被調(diào)用函數(shù)最近的對(duì)象(window也是對(duì)象养晋,其內(nèi)部對(duì)象調(diào)用方法的this指向內(nèi)部對(duì)象, 而非window)登馒。

//1varo = {prop:37,f:function(){returnthis.prop;? }};console.log(o.f());//37vara = o.f;console.log(a())://undefinedvaro = {prop:37};functionindependent(){returnthis.prop;}o.f = independent;console.log(o.f());// logs 37//2o.b = {g: independent,prop:42};console.log(o.b.g());// logs 42

原型鏈中this

原型鏈中的方法的this仍然指向調(diào)用它的對(duì)象匙握,與以上討論一致;看個(gè)例子陈轿,

varo = {f:function(){returnthis.a +this.b;? }};varp =Object.create(o);p.a =1;p.b =4;console.log(p.f());// 5

可以看出圈纺, 在p中沒有屬性f秦忿,當(dāng)執(zhí)行p.f()時(shí),會(huì)查找p的原型鏈蛾娶,找到 f 函數(shù)并執(zhí)行灯谣,但這與函數(shù)內(nèi)部this指向?qū)ο?p 沒有任何關(guān)系,只需記住誰調(diào)用指向誰蛔琅。

以上對(duì)于函數(shù)作為getter & setter 調(diào)用時(shí)同樣適用胎许。

構(gòu)造函數(shù)中this

構(gòu)造函數(shù)中的this與被創(chuàng)建的新對(duì)象綁定。

注意:當(dāng)構(gòu)造器返回的默認(rèn)值是一個(gè)this引用的對(duì)象時(shí)罗售,可以手動(dòng)設(shè)置返回其他的對(duì)象辜窑,如果返回值不是一個(gè)對(duì)象,返回this寨躁。

functionC(){this.a =37;}varo =newC();console.log(o.a);// logs 37functionC2(){this.a =37;return{a:38};}varb =newC2();console.log(b.a);// logs 38

以上兩個(gè)例子內(nèi)部的this都指向?qū)ο髈, 看到這里的你不妨在控制臺(tái)執(zhí)行下以上代碼穆碎,看看對(duì)象 o 和 b ,這些是屬于構(gòu)造函數(shù)的內(nèi)容了职恳,此處不多做介紹所禀。(C2函數(shù)中的this.a = 37 對(duì)整個(gè)過程完全沒有影響的, 可以被忽略的)放钦。

call & apply

當(dāng)函數(shù)通過Function對(duì)象的原型中繼承的方法 call() 和 apply() 方法調(diào)用時(shí)色徘, 其函數(shù)內(nèi)部的this值可綁定到 call() & apply() 方法指定的第一個(gè)對(duì)象上, 如果第一個(gè)參數(shù)不是對(duì)象操禀,JavaScript內(nèi)部會(huì)嘗試將其轉(zhuǎn)換成對(duì)象然后指向它褂策。

例子:

functionadd(c, d){returnthis.a + this.b + c + d;}var o = {a:1, b:3};add.call(o,5,7); //1+3+5+7=16add.apply(o, [10,20]); //1+3+10+20=34functiontt(){? console.log(this);}// 返回對(duì)象見下圖(圖1)tt.call(5);? // Number {[[PrimitiveValue]]:5} tt.call('asd'); // String {0:"a",1:"s",2:"d", length:3,[[PrimitiveValue]]:"asd"}

bind 方法

bind方法在ES5引入, 在Function的原型鏈上床蜘,?Function.prototype.bind辙培。通過bind方法綁定后, 函數(shù)將被永遠(yuǎn)綁定在其第一個(gè)參數(shù)對(duì)象上邢锯, 而無論其在什么情況下被調(diào)用扬蕊。

functionf(){returnthis.a;}varg = f.bind({a:"azerty"});console.log(g());// azertyvaro = {a:37,f:f,g:g};console.log(o.f(), o.g());// 37, azerty

DOM 事件處理函數(shù)中的 this & 內(nèi)聯(lián)事件中的 this

DOM事件處理函數(shù)

當(dāng)函數(shù)被當(dāng)做監(jiān)聽事件處理函數(shù)時(shí), 其 this 指向觸發(fā)該事件的元素 (針對(duì)于addEventListener事件)

// 被調(diào)用時(shí)丹擎,將關(guān)聯(lián)的元素變成藍(lán)色functionbluify(e){//在控制臺(tái)打印出所點(diǎn)擊元素console.log(this);//阻止時(shí)間冒泡e.stopPropagation();//阻止元素的默認(rèn)事件e.preventDefault();this.style.backgroundColor ='#A5D9F3';? ? }// 獲取文檔中的所有元素的列表varelements =document.getElementsByTagName('*');// 將bluify作為元素的點(diǎn)擊監(jiān)聽函數(shù)尾抑,當(dāng)元素被點(diǎn)擊時(shí),就會(huì)變成藍(lán)色for(vari=0; i

以上代碼建議在網(wǎng)頁中執(zhí)行以下蒂培,看下效果再愈。

內(nèi)聯(lián)事件

內(nèi)聯(lián)事件中的this指向分兩種情況:

當(dāng)代碼被內(nèi)聯(lián)處理函數(shù)調(diào)用時(shí),它的this指向監(jiān)聽器所在的DOM元素

當(dāng)代碼被包括在函數(shù)內(nèi)部執(zhí)行時(shí)护戳,其this指向等同于 ****函數(shù)直接調(diào)用****的情況翎冲,即在非嚴(yán)格模式指向全局對(duì)象window, 在嚴(yán)格模式指向undefined

頁面的代碼塊

在瀏覽器內(nèi)顯示三個(gè)按鈕

依次點(diǎn)擊上邊的三個(gè)按鈕后在控制臺(tái)的輸出結(jié)果媳荒,

建議自己操作一遍以便于更好的理解抗悍。

setTimeout & setInterval

對(duì)于延時(shí)函數(shù)內(nèi)部的回調(diào)函數(shù)的this指向全局對(duì)象window(當(dāng)然我們可以通過bind方法改變其內(nèi)部函數(shù)的this指向)

看下邊代碼及截圖

//默認(rèn)情況下代碼functionPerson(){this.age =0;? ? ? setTimeout(function(){console.log(this);? ? },3000);}varp =newPerson();//3秒后返回 window 對(duì)象==============================================//通過bind綁定functionPerson(){this.age =0;? ? ? setTimeout((function(){console.log(this);? ? }).bind(this),3000);}varp =newPerson();//3秒后返回構(gòu)造函數(shù)新生成的對(duì)象 Person{...}

箭頭函數(shù)中的 this

由于箭頭函數(shù)不綁定this驹饺, 它會(huì)捕獲其所在(即定義的位置)上下文的this值, 作為自己的this值缴渊,

所以 call() / apply() / bind() 方法對(duì)于箭頭函數(shù)來說只是傳入?yún)?shù)赏壹,對(duì)它的 this 毫無影響。

考慮到 this 是詞法層面上的衔沼,嚴(yán)格模式中與 this 相關(guān)的規(guī)則都將被忽略蝌借。(可以忽略是否在嚴(yán)格模式下的影響)

因?yàn)榧^函數(shù)可以捕獲其所在上下文的this值 所以

functionPerson(){this.age =0;? ? ? setInterval(()=>{// 回調(diào)里面的 `this` 變量就指向了期望的那個(gè)對(duì)象了this.age++;? ? },3000);}varp =newPerson();

以上代碼可以得到我們所以希望的值,下圖可以看到指蚁,在setTimeout中的this指向了構(gòu)造函數(shù)新生成的對(duì)象菩佑,而普通函數(shù)指向了全局window對(duì)象

varadder = {base:1,add:function(a){varf =v=>v +this.base;returnf(a);? },addThruCall:functioninFun(a){varf =v=>v +this.base;varb = {base:2};returnf.call(b, a);? }};console.log(adder.add(1));// 輸出 2console.log(adder.addThruCall(1));// 仍然輸出 2(而不是3,其內(nèi)部的this并沒有因?yàn)閏all() 而改變欣舵,其this值仍然為函數(shù)inFun的this值擎鸠,指向?qū)ο骯dder

bind() & apply() 讀者可以自行測(cè)試

對(duì)于是否嚴(yán)格模式示例代碼(可以復(fù)制進(jìn)控制臺(tái)進(jìn)行驗(yàn)證)

varf =()=>{'use strict';returnthis};varp =()=>{returnthis};console.log(1,f() ===window);console.log(2,f() === p());//1 true//2 true

以上的箭頭函數(shù)都是在方法內(nèi)部,總之都是以非方法的方式使用缘圈,如果將箭頭函數(shù)當(dāng)做一個(gè)方法使用會(huì)怎樣呢?

上例子

varobj = {i:10,b:()=>console.log(this.i,this),c:function(){console.log(this.i,this)? }}obj.b();// undefined window{...}obj.c();// 10 Object {...}

可以看到袜蚕,作為方法的箭頭函數(shù)this指向全局window對(duì)象糟把,而普通函數(shù)則指向調(diào)用它的對(duì)象

以上為個(gè)人學(xué)習(xí)整理內(nèi)容, 文中例子參考MDN牲剃, 歡迎交流學(xué)習(xí)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遣疯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凿傅,更是在濱河造成了極大的恐慌缠犀,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聪舒,死亡現(xiàn)場(chǎng)離奇詭異辨液,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)箱残,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門滔迈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人被辑,你說我怎么就攤上這事燎悍。” “怎么了盼理?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵谈山,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我宏怔,道長(zhǎng)奏路,這世上最難降的妖魔是什么畴椰? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮思劳,結(jié)果婚禮上迅矛,老公的妹妹穿的比我還像新娘。我一直安慰自己潜叛,他們只是感情好秽褒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著威兜,像睡著了一般销斟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上椒舵,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天蚂踊,我揣著相機(jī)與錄音,去河邊找鬼笔宿。 笑死犁钟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泼橘。 我是一名探鬼主播涝动,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼炬灭!你這毒婦竟也來了醋粟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤重归,失蹤者是張志新(化名)和其女友劉穎米愿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鼻吮,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡育苟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狈网。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宙搬。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拓哺,靈堂內(nèi)的尸體忽然破棺而出勇垛,到底是詐尸還是另有隱情,我是刑警寧澤士鸥,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布闲孤,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏讼积。R本人自食惡果不足惜肥照,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望勤众。 院中可真熱鬧舆绎,春花似錦、人聲如沸们颜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窥突。三九已至努溃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阻问,已是汗流浹背梧税。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留称近,地道東北人第队。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像刨秆,于是被迫代替她去往敵國和親斥铺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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

  • 本文地址:http://www.reibang.com/p/16dd8acb0b13 前言 this 指向問題是入...
    Chris_dc閱讀 3,180評(píng)論 2 5
  • ES6 允許使用 “ 箭頭 ” (=>)定義函數(shù)坛善。 箭頭函數(shù) 填 坑。 this的指向是 向上查找 非箭頭函數(shù)的...
    kismetajun閱讀 800評(píng)論 0 12
  • 首先對(duì)this的下個(gè)定義:this是在執(zhí)行上下文創(chuàng)建時(shí)確定的一個(gè)在執(zhí)行過程中不可更改的變量邻眷。 this只在函數(shù)調(diào)用...
    阿良__閱讀 1,877評(píng)論 1 1
  • JavaScript(面向?qū)ο?原型理解+繼承+作用域鏈和閉包+this使用總結(jié)) 一眠屎、面向?qū)ο?1、什么是面向?qū)?..
    老頭子_d0ec閱讀 297評(píng)論 0 0
  • 與其他語言相比肆饶,函數(shù)的 this 關(guān)鍵字在JavaScript中的行為略有不同改衩。它在嚴(yán)格模式和非嚴(yán)格模式之間也有一...
    binginto閱讀 199評(píng)論 0 1