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