摘要:例如通過(guò),調(diào)用時(shí)強(qiáng)制把它的綁定到上。箭頭函數(shù)問(wèn)題箭頭函數(shù)體內(nèi)的對(duì)象就是定義時(shí)所在的對(duì)象,而不是使用時(shí)所在的對(duì)象,固定不變。
剛?cè)腴Tjavascript,關(guān)于this的學(xué)習(xí),花了自己挺多的時(shí)間,做了比較多的功課,看了一篇又一篇的文章,也看了一些書(shū)籍,今天就結(jié)合看的那些東西總結(jié)下自己所學(xué)到的東西,方便留著以后回看,進(jìn)一步的學(xué)習(xí),這篇文章會(huì)不斷的更新,不斷的更新自己的想法,現(xiàn)在還是一個(gè)入門不久的小白,若有錯(cuò)誤,懇請(qǐng)指出!
this這個(gè)關(guān)鍵字在整個(gè)javascript中用處挺廣泛的,例如,在閉包,對(duì)象等中都會(huì)用到,掌握好this個(gè)人認(rèn)為是學(xué)好javascript的關(guān)鍵之一了,當(dāng)然其中還有:閉包、原型、原型鏈、對(duì)象等理論基礎(chǔ)也是幾個(gè)關(guān)鍵點(diǎn),都得用心的學(xué)習(xí)。
函數(shù)中的調(diào)用
javascript函數(shù)中this的指向不是在函數(shù)定義的時(shí)候確定的,而是在函數(shù)調(diào)用時(shí)確定的,用我自己的話來(lái)說(shuō):就是看這個(gè)函數(shù)是在什么環(huán)境下被調(diào)用的,如果在全局環(huán)境下調(diào)用這個(gè)函數(shù),那么這個(gè)函數(shù)中的this就指向了window,看下面的這個(gè)例子:
var a = 2; function foo() { console.log(this.a);//2 } foo();
函數(shù)foo()的調(diào)用是在全局環(huán)境下調(diào)用的,即這個(gè)函數(shù)中的this指向的就是window(其實(shí)這也可以叫函數(shù)的默認(rèn)綁定,在后面我會(huì)介紹),函數(shù)控制臺(tái)輸出的就是window.a,函數(shù)內(nèi)部即使沒(méi)有定義變量,同樣也是可以輸出a的值,這其中也涉及到了作用域鏈的相關(guān)知識(shí)點(diǎn),由內(nèi)向外搜索,這里就不解釋了,這個(gè)可以自己去了解。
加大一點(diǎn)難度,看看這個(gè)例子,可能會(huì)讓你開(kāi)始有點(diǎn)迷惑,我自己在不是很理解this在函數(shù)中的調(diào)用,是很迷惑的,不懂,相關(guān)知識(shí)點(diǎn)一遍一遍的反復(fù)的看,大家來(lái)看看,是上面的例子的改版:
var a = 2; function foo() { var a = 3; console.log(this.a);//2 } foo();
這個(gè)函數(shù)foo()的輸出值,大家應(yīng)該會(huì)感到很意外,我去,a怎么會(huì)輸出的是2,不應(yīng)該是3的嗎,是不是有問(wèn)題啊,哈哈哈哈哈,起初我是覺(jué)得是有問(wèn)題的,函數(shù)中明明也聲明了一個(gè)變量a,輸出的值肯定是3啊,想了一些時(shí)間沒(méi)有想明白?;剡^(guò)頭來(lái)看看this是怎么說(shuō)的,就清楚了為什么a輸出的值依舊是2了:javascript函數(shù)中this的指向不是在函數(shù)定義的時(shí)候確定的,而是在函數(shù)調(diào)用時(shí)確定的。認(rèn)真的解讀下這句話就很清楚的知道變量a輸出的值肯定就是2了,this的指向只與普通函數(shù)的調(diào)用有關(guān),箭頭函數(shù)另外再說(shuō),這個(gè)foo()函數(shù)的調(diào)用時(shí)在全局環(huán)境,因此this是指向全局對(duì)象,即window,所以輸出a的值依舊還是2了,而不是想當(dāng)然的認(rèn)為是3了,這下應(yīng)該比較清楚了吧。大家再看下下面的這個(gè)例子:
var a = 2; function foo() { a = 3; console.log(this.a); } foo();
這個(gè)foo()函數(shù)輸出的又是什么值呢,這個(gè)就是大家認(rèn)為的3了,這就不解釋了,看了上面的應(yīng)該就比較清楚了。
綁定規(guī)則
默認(rèn)綁定
函數(shù)獨(dú)立調(diào)用,直接使用不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用,其this默認(rèn)指向window對(duì)象,第一部分的第一個(gè)例子就是默認(rèn)綁定,這就不在記述。
隱式綁定
函數(shù)調(diào)用時(shí)擁有一個(gè)上下文對(duì)象,就好像這個(gè)函數(shù)是屬于這個(gè)對(duì)象的一樣。例如:
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; obj.foo();//2
當(dāng)函數(shù)foo()被調(diào)用時(shí),其引用有obj這個(gè)對(duì)象,即函數(shù)調(diào)用中的this綁定到了這個(gè)對(duì)象,this.a就相當(dāng)于obj.a,輸出的值就為2。
隱式綁定丟失
被隱式綁定的函數(shù)丟失綁定對(duì)象,其會(huì)應(yīng)用默認(rèn)綁定,這也是this應(yīng)用中容易出錯(cuò)的地方,關(guān)鍵還是對(duì)this調(diào)用位置沒(méi)有理解清楚。例如:
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; var bar = obj.foo; var a = "全局"; bar();// "全局"
其實(shí)很好理解為什么this指向的全局對(duì)象window,關(guān)鍵還是看函數(shù)的調(diào)用位置,雖然函數(shù)foo()被當(dāng)作引用添加到obj對(duì)象中,它也僅僅是一個(gè)引用,變量bar也就是obj.foo的一個(gè)引用的傳遞,然而bar()是獨(dú)立調(diào)用的,不帶任何修飾的函數(shù)調(diào)用,所以函數(shù)調(diào)用中的this是綁定到了全局對(duì)象,即this.a是window.a,輸出的值為"全局"。
顯式綁定
顯式綁定多數(shù)是用call()、apply()函數(shù),他們的第一個(gè)參數(shù)是一個(gè)對(duì)象,是給this準(zhǔn)備的,函數(shù)調(diào)用時(shí)將其綁定到this,也就是直接指定this的綁定對(duì)象。例如:
function foo(){ console.log(this.a); } var obj = { a:2 }; foo.call(obj);//2
通過(guò)call(),調(diào)用foo時(shí)強(qiáng)制把它的this綁定到obj上。
apply()的使用和call()一樣,它們不同的在于傳參的方式不一樣,call()接受的是若干個(gè)參數(shù)的列表,apply()接受的是一個(gè)包含多個(gè)參數(shù)的數(shù)組,具體作用可以自己去了解。
new綁定
如果是一個(gè)構(gòu)造函數(shù),用new來(lái)調(diào)用,那么綁定的將是新創(chuàng)建的對(duì)象。例如:
function foo(a){ this.a = a; } var bar = new foo(2); console.log(bar.a);//2
使用new來(lái)調(diào)用foo()時(shí),構(gòu)造一個(gè)新的對(duì)象并把它綁定到函數(shù)調(diào)用中的this上面,即this.a就是bar.a,輸出的值為2。
箭頭函數(shù)this問(wèn)題
箭頭函數(shù)體內(nèi)的this對(duì)象就是定義時(shí)所在的對(duì)象,而不是使用時(shí)所在的對(duì)象,固定不變。例如:
function foo(){ setTimeout(()=>{ console.log(this.a); },100); } var obj = { a:2 } foo.call(obj);//2 function foo(){ setTimeout(function(){ console.log(this.a); },100); } var obj = { a:2 } foo.call(obj);//undefined
看上面的兩個(gè)例子,第一個(gè)使用的是箭頭函數(shù),第二個(gè)使用的是普通函數(shù),最后的結(jié)果不一樣的,輸出一個(gè)是2,一個(gè)是undefined。原因很簡(jiǎn)單,箭頭函數(shù)中this對(duì)象是在定義所在的的對(duì)象,普通函數(shù)中的this對(duì)象的指向是可變的。
本例第一個(gè)用例中箭頭函數(shù)中的this總是指向函數(shù)定義生效時(shí)所在的對(duì)象,即為obj,所以箭頭函數(shù)的this.a就是obj.a,輸出的值就為2。第二個(gè)用例中,根據(jù)調(diào)用的位置,普通函數(shù)this的指向是可變的,這個(gè)用例中this的最終指向的是全局對(duì)象window,即this.a就是window.a,全局環(huán)境中沒(méi)有定義變量啊,所以輸出的值為undefined。為什么第二個(gè)用例的this指向的是全局對(duì)象,有一種解釋是:對(duì)象中的方法的函數(shù)被當(dāng)作函數(shù)模式所觸發(fā),所以它的this是指向window的,這也是this應(yīng)用容易出錯(cuò)的一個(gè)地方。如果也想讓它的this指向定義時(shí)綁定的對(duì)象,做如下改變就行了:
function foo(){ var that = this; setTimeout(function(){ console.log(that.a); },100); } var obj = { a:2 } foo.call(obj);//2
將this臨時(shí)傳遞給一個(gè)變量that,通過(guò)that使用,這樣輸出的值就為2了。
結(jié)束
1.this的掌握的關(guān)鍵在于它的調(diào)用位置,這個(gè)理解清楚了就不太容易出錯(cuò)。
2.要區(qū)分好普通函數(shù)和箭頭函數(shù)中this的使用,不要搞混淆了。
3.學(xué)好這些理論基礎(chǔ)是學(xué)好javascript的基石,對(duì)以后理解和寫javascript的邏輯提供很好的幫助
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/89652.html
摘要:總結(jié)本博文通過(guò)介紹執(zhí)行上下文和作用域的異同的使用以及變量對(duì)象,讓我們加深對(duì)語(yǔ)言特性的理解。首先,我們介紹了執(zhí)行上下文和的的關(guān)系,并且執(zhí)行上下文是具有對(duì)象的然后,介紹了作用域使變量在作用域范圍內(nèi)可見(jiàn),并且作用域是基于函數(shù)的。 接上一篇Javascript Context和Scope的學(xué)習(xí)總結(jié)01【轉(zhuǎn)自cnblogs的JKhuang】(可能是segmentfault對(duì)單篇文章發(fā)布字?jǐn)?shù)有限制...
摘要:全局環(huán)境在全局環(huán)境中使用,它會(huì)指向全局對(duì)象。作為構(gòu)造函數(shù)調(diào)用中的構(gòu)造函數(shù)很特殊,如果不使用調(diào)用,則和普通函數(shù)一樣。作為又一項(xiàng)約定俗成的準(zhǔn)則,構(gòu)造函數(shù)以大寫字母開(kāi)頭,提醒調(diào)用者使用正確的方式調(diào)用。 在JavaScript中,this關(guān)鍵字是動(dòng)態(tài)綁定的,或稱為運(yùn)行期綁定,這極大地增強(qiáng)的我們程序的靈活性,同時(shí)也給初學(xué)者帶來(lái)了很多困惑。本文總結(jié)了this的幾個(gè)使用場(chǎng)景和常見(jiàn)誤區(qū)。 全局環(huán)境 在...
摘要:發(fā)生這種情況的條件是當(dāng)引用類型值的對(duì)象恰好為活躍對(duì)象??偨Y(jié)本文介紹中的使用,更重要的是幫助我們能更好地理解值在全局函數(shù)構(gòu)造函數(shù)以及一些特例的情況中值的變化。然而,由于對(duì)于來(lái)說(shuō)沒(méi)有任何意義,因此會(huì)隱式轉(zhuǎn)換為全局對(duì)象。 接上一篇Javascript this 的一些學(xué)習(xí)總結(jié)02【轉(zhuǎn)自cnblogs的JKhuang】 引用類型以及this的null值 對(duì)于前面提及的情形,還有例外的情況,當(dāng)調(diào)...
摘要:布爾值表示捕獲階段調(diào)用事件處理程序,表示冒泡階段通過(guò)對(duì)象的方法,也可以定義事件的回調(diào)函數(shù)。對(duì)象會(huì)被作為第一個(gè)參數(shù)傳遞給事件監(jiān)聽(tīng)的回調(diào)函數(shù)。布爾默認(rèn)值是,當(dāng)設(shè)置成時(shí)用以取消事件的默認(rèn)行為與中的相同。 其實(shí)這篇文章挺早之前就寫了,但是由于sf保存方面的bug,所以當(dāng)時(shí)寫了一大堆,結(jié)果沒(méi)保存,覺(jué)得這個(gè)沒(méi)寫完是個(gè)不小的遺憾,今天正好有空,就給補(bǔ)充下了,也正好給我的javascript學(xué)習(xí)總結(jié)做...
摘要:正文執(zhí)行環(huán)境也稱為環(huán)境是中最為重要的一個(gè)概念。執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問(wèn)的其他數(shù)據(jù),決定了它們各自的行為。簡(jiǎn)而言之,執(zhí)行環(huán)境是基于對(duì)象的,而作用域是基于函數(shù)的。 前述 在我們學(xué)習(xí)Javascript過(guò)程中,常常會(huì)遇到作用域(Scope)和執(zhí)行上下文(Context)等概念。其中,執(zhí)行上下文與this關(guān)鍵字的關(guān)系密切。 有面向?qū)ο缶幊探?jīng)驗(yàn)的各位,對(duì)于this關(guān)鍵字再熟悉不過(guò)了,因此...
閱讀 1953·2021-11-19 09:40
閱讀 2677·2021-08-30 09:46
閱讀 2243·2021-08-03 14:01
閱讀 2694·2019-08-30 10:54
閱讀 1264·2019-08-29 16:38
閱讀 1497·2019-08-29 11:02
閱讀 2599·2019-08-28 18:16
閱讀 1766·2019-08-28 18:09