摘要:關(guān)鍵字是中一個(gè)復(fù)雜的機(jī)制,它被自動(dòng)定義在所有的函數(shù)作用域中。指向它自身匿名函數(shù)無(wú)法指向自身第一個(gè)函數(shù)被稱為具名函數(shù),在它內(nèi)部可以使用來(lái)引用自身。的綁定和函數(shù)聲明的位置沒有任何關(guān)系,取決于函數(shù)的調(diào)用方式。這是理解的前提。
this關(guān)鍵字是JavaScript中一個(gè)復(fù)雜的機(jī)制,它被自動(dòng)定義在所有的函數(shù)作用域中。
1. 為什么要用thisfunction identify() { return this.name.toUpperCase() } function speak() { var greeting = "hello, i"am" + identify.call(this) console.log(greeting) } var me = { name: "Kyle" } var you = { name: "Reader" } identify.call(me); //KYLE identify.call(you) //READER speak.call(me) //Hello, 我是KYLE speak.call(you) //Hello, 我是READER
上面這部分代碼在不同的上下文對(duì)象中重復(fù)使用identify()和speak(),不用針對(duì)每個(gè)對(duì)象編寫不同版本的函數(shù)。
如果不使用this,那就需要給identify()和speak()顯示傳入一個(gè)上下文對(duì)象。
function identify(context) { return context.name.toUpperCase(); } function speak(context) { var greeting = "Hello i"am" + identify(context) console.log(greeting) } identify(you) //READER speak(me) //hello, 我是KYLE
然而,this提供了一種更優(yōu)雅的方式來(lái)隱式傳遞一個(gè)對(duì)象引用,因此可以將API設(shè)計(jì)的更加簡(jiǎn)潔且易于復(fù)用。
當(dāng)你的代碼越來(lái)越復(fù)雜的時(shí)候,顯示的傳遞上下文對(duì)象會(huì)變得很混亂。
通常會(huì)將this理解成指向函數(shù)自身。平常我們會(huì)在函數(shù)內(nèi)部調(diào)用自身(例如遞歸)。在JavaScript中函數(shù)也是一個(gè)對(duì)象,那么我們可以在調(diào)用函數(shù)的時(shí)候存儲(chǔ)狀態(tài)(屬性的值)。
我們看下以下代碼,會(huì)發(fā)現(xiàn)this并沒有指向函數(shù)本身:
//記錄foo的調(diào)用次數(shù) function foo(num) { console.log("foo: "+ num) this.count ++ } foo.count = 0; var i; for(i=0; i<10; i++) { if(i>5) { foo(i) } } //foo: 6 //foo: 7 //foo: 8 //foo: 9 //foo 被調(diào)用了多少次? console.log(foo.count) //0
可以看到foo()執(zhí)行了4次,但是foo.count仍然是0,所以從字面上理解this指向的是當(dāng)前函數(shù)自身就是錯(cuò)誤的!
在執(zhí)行foo.count=0的時(shí)候,確實(shí)向函數(shù)對(duì)象foo添加了一個(gè)count屬性,但是函數(shù)內(nèi)部的this.count的this并不是指向那個(gè)函數(shù)對(duì)象(其實(shí)是window對(duì)象)。
那么增加的是哪個(gè)count?這是創(chuàng)建在全局變量的一個(gè)count,值為NaN.
如果要從函數(shù)對(duì)象內(nèi)部引用它自身,那只使用this是不夠的。一般你需要通過(guò)一個(gè)指向函數(shù)對(duì)象的詞法標(biāo)識(shí)符來(lái)引用。
function foo() { foo.count = 4 //foo指向它自身 } setTimeout(function() { //匿名函數(shù)無(wú)法指向自身 }, 10)
第一個(gè)函數(shù)被稱為具名函數(shù),在它內(nèi)部可以使用foo來(lái)引用自身。但是在第二個(gè)例子中,傳入setTimeout(..)的回調(diào)函數(shù)沒有名稱標(biāo)識(shí)符,因此無(wú)法從函數(shù)內(nèi)部引用自身。
還有一種方法是通過(guò)強(qiáng)制this指向foo函數(shù)對(duì)象:
function foo(num) { console.log("foo:" + num) this.count ++ } foo.count = 0 var i; for(i=0; i<10; i++) { if(i>5) { foo.call(foo, i) } }
如上,我們強(qiáng)制this指向了foo,這樣就可以獲得我們想要的答案了。
誤解之它的作用域第二種錯(cuò)誤的理解是this指向函數(shù)的作用域。這個(gè)問題有些復(fù)雜,因?yàn)樵谀撤N情況下它是正確的。
需要明確的是,this在任何情況下都不指向函數(shù)的詞法作用域。在JavaScript內(nèi)部,作用域確實(shí)很像對(duì)象,可見的標(biāo)識(shí)符都是它的屬性。但是作用域?qū)ο笫菬o(wú)法通過(guò)JavaScript代碼進(jìn)行訪問,它是在JavaScript引擎內(nèi)部。
function foo() { var a = 2; this.bar(); } function bar() { console.log(this.a) } foo(); // a is not defined
以上代碼運(yùn)行是不會(huì)得到你理想的結(jié)果的,因?yàn)槟悴荒苁褂胻his來(lái)引用一個(gè)詞法作用域內(nèi)部的東西。
3. this到底是什么this是在運(yùn)行時(shí)進(jìn)行綁定的,并不是在編寫時(shí)綁定,它的上下文取決于函數(shù)調(diào)用時(shí)的各種條件。this的綁定和函數(shù)聲明的位置沒有任何關(guān)系,取決于函數(shù)的調(diào)用方式。
當(dāng)一個(gè)函數(shù)調(diào)用時(shí),會(huì)創(chuàng)建一個(gè)活動(dòng)記錄(有時(shí)候也稱為執(zhí)行上下文)。這個(gè)記錄 會(huì)包含函數(shù)在哪里被調(diào)用(調(diào)用棧),函數(shù)的調(diào)用方法,傳入的參數(shù)信息。this就是記錄的其中一個(gè)屬性,會(huì)在函數(shù)執(zhí)行的過(guò)程中用到。
總結(jié)這里我們要明白this既不是指向函數(shù)自身,也不是指向函數(shù)的詞法作用域。這是理解this的前提。
this實(shí)際上時(shí)在函數(shù)被調(diào)用時(shí)發(fā)生的綁定,它指向什么完全取決于函數(shù)在哪里被調(diào)用。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/89948.html
摘要:找到函數(shù)的調(diào)用位置最重要的是要分析調(diào)用棧就是為了到達(dá)當(dāng)前執(zhí)行位置所調(diào)用的所有函數(shù)。顯示綁定我們可以使用函數(shù)的和方法,通過(guò)這兩個(gè)方法可以在某個(gè)對(duì)象上強(qiáng)制調(diào)用函數(shù)。 在上一篇我們了解過(guò)每個(gè)函數(shù)的this是在調(diào)用的時(shí)候綁定的,完全卻決于函數(shù)的調(diào)用位置(也就是函數(shù)的調(diào)用方法)。 1. 調(diào)用位置 在理解this的綁定過(guò)程之前,首先要理解調(diào)用位置:調(diào)用位置就是函數(shù)在代碼中被調(diào)用的位置,而不是聲明的...
摘要:下面開始分析開頭的代碼第一輪事件循環(huán)流程整體作為第一個(gè)宏任務(wù)進(jìn)入主線程,遇到,輸出遇到函數(shù)聲明,聲明暫時(shí)不用管遇到,其回調(diào)函數(shù)被分發(fā)到微任務(wù)中。我們記為遇到,其回調(diào)函數(shù)被分發(fā)到宏任務(wù)中。 先上一道常見的筆試題 console.log(1); async function async1() { console.log(2); await async2(); con...
摘要:下面開始分析開頭的代碼第一輪事件循環(huán)流程整體作為第一個(gè)宏任務(wù)進(jìn)入主線程,遇到,輸出遇到函數(shù)聲明,聲明暫時(shí)不用管遇到,其回調(diào)函數(shù)被分發(fā)到微任務(wù)中。我們記為遇到,其回調(diào)函數(shù)被分發(fā)到宏任務(wù)中。 先上一道常見的筆試題 console.log(1); async function async1() { console.log(2); await async2(); con...
摘要:是什么本質(zhì)是一個(gè)綁定,在函數(shù)被調(diào)用時(shí)建立。它的指向是完全由函數(shù)被調(diào)用的調(diào)用點(diǎn)來(lái)決定的。因?yàn)楹瘮?shù)的調(diào)用點(diǎn)在全局作用域,所以指向全局變量這里就是函數(shù)的調(diào)用點(diǎn)存在的意義在函數(shù)體內(nèi)部指代函數(shù)當(dāng)前的運(yùn)行環(huán)境。從而實(shí)現(xiàn)干凈的設(shè)計(jì)和更容易的復(fù)用。 this是什么? this 本質(zhì)是一個(gè)綁定, 在函數(shù)被調(diào)用時(shí)建立。它的指向是完全由函數(shù)被調(diào)用的調(diào)用點(diǎn)來(lái)決定的。 function baz() { ...
摘要:而小程序官方的是在中調(diào)用方法來(lái)改變數(shù)據(jù),從而改變界面。為了寫測(cè)試讓咱們來(lái)重構(gòu)一把,利用學(xué)習(xí)過(guò)的函數(shù)式編程中的高階函數(shù)把依賴注入。也就是說(shuō)當(dāng)中的某個(gè)數(shù)據(jù)更新的時(shí)候,我們并不知道它會(huì)影響哪個(gè)中的屬性,特別的還有依賴于的情況。 眾所周知 Vue 是借助 ES5 的 Object.defineProperty 方法設(shè)置 getter、setter 達(dá)到數(shù)據(jù)驅(qū)動(dòng)界面,當(dāng)然其中還有模板編譯等等其他...
閱讀 3114·2021-10-14 09:50
閱讀 1320·2021-10-08 10:21
閱讀 3773·2021-10-08 10:16
閱讀 3159·2021-09-27 14:02
閱讀 3209·2021-09-23 11:21
閱讀 2332·2021-09-07 10:17
閱讀 467·2019-08-30 14:00
閱讀 2206·2019-08-29 17:26