摘要:本內(nèi)容來(lái)自你不知道的上卷,做了簡(jiǎn)單的總結(jié)。如果不使用這段代碼該如何寫呢那就需要給和顯示傳入一個(gè)上下文對(duì)象對(duì)比發(fā)現(xiàn)提供了額一種更優(yōu)雅的方式來(lái)隱式傳遞一個(gè)對(duì)象引用。四總結(jié)隨著你使用的模式越來(lái)越復(fù)雜,顯式傳遞上下文對(duì)象會(huì)讓代碼變得越來(lái)越混亂。
本內(nèi)容來(lái)自《你不知道的JavaScript(上卷)》,做了簡(jiǎn)單的總結(jié)。
this關(guān)鍵字是javascript最復(fù)雜的機(jī)制之一。它是一個(gè)很特別的關(guān)鍵字,被自動(dòng)定義在所有的函數(shù)作用域中。但是即使是非常有經(jīng)驗(yàn)的javascript開(kāi)發(fā)者也很難說(shuō)出他到底指向什么。本節(jié)將分三個(gè)部分講解javascript中的this:
為什么要使用this
兩種常見(jiàn)的對(duì)于this的誤解
this到底是什么
一、為什么要使用this在書(shū)中通過(guò)兩段代碼的對(duì)比來(lái)說(shuō)明為什么要使用this。第一段代碼如下:這段代碼在不同的上下問(wèn)對(duì)象(me和you)中重復(fù)使用函數(shù)identify()和speak(),不用針對(duì)不同的對(duì)象編寫不同版本的函數(shù)。
function identify(){ return this.name.toUpperCase(); } function speak(){ var greeting = "hello, I am " + identify.call(this); console.log(greeting); } var me = { name: "zhou" } var you = { name: "reader" } identify.call(me); //ZHOU identify.call(you); //READER speak.call(me); // hello, I am ZHOU speak.call(you); // hello, I am READER
如果不使用this, 這段代碼該如何寫呢?那就需要給identify()和speak()顯示傳入一個(gè)上下文對(duì)象
function identify(cxt){ return cxt.name.toUpperCase(); } function speak(cxt){ var greeting = "hello, I am " + identify(cxt); console.log(greeting); } identify(you); //READER speak(me); //hello, I am ZHOU
對(duì)比發(fā)現(xiàn):this提供了額一種更優(yōu)雅的方式來(lái)隱式“傳遞”一個(gè)對(duì)象引用。因?yàn)?,隨著你使用的模式越來(lái)越復(fù)雜,顯式傳遞上下文對(duì)象會(huì)讓代碼變得越來(lái)越混亂。因此,通過(guò)使用this可以將API設(shè)計(jì)的更加簡(jiǎn)潔并且易于復(fù)用。
二、兩種常見(jiàn)的對(duì)于this的誤解 誤解1.指向函數(shù)自身把this理解為指向函數(shù)自身,這個(gè)推斷從英語(yǔ)語(yǔ)法角度是說(shuō)的通的。
常見(jiàn)的在函數(shù)內(nèi)部引用自身的情況有:遞歸或者是一個(gè)在第一次被調(diào)用后自己接觸綁定的事件處理器。 JavaScript的新手開(kāi)發(fā)者(比如說(shuō)我)通常認(rèn)為:既然可以把函數(shù)看作一個(gè)對(duì)象,那就可以在調(diào)用函數(shù)時(shí)存儲(chǔ)狀態(tài)(屬性的值)。
現(xiàn)在我們來(lái)分析這個(gè)模式,讓大家看到this并不像所想的那樣指向函數(shù)本身。下面這段代碼,我們想要記錄函數(shù)foo被調(diào)用的次數(shù):
function foo(num){ console.log("foo: " + num); this.count++; //記錄foo被調(diào)用的次數(shù) } foo.count = 0; for(var i=0; i<10; i++){ if(i > 5){ foo(i) } } // foo: 6 // foo: 7 // foo: 8 // foo: 9 console.log(foo.count); // 0 為什么會(huì)是0呢?
foo()函數(shù)中的console.log語(yǔ)句產(chǎn)生了4條輸出,證明foo()確實(shí)被調(diào)用了4次,但foo.count仍然是0,所以,僅從字面上來(lái)理解,this指向函數(shù)自身是錯(cuò)誤的。那么,問(wèn)題的原因是什么呢?
foo()函數(shù)是在全局作用域下執(zhí)行的,this在這段代碼中其實(shí)指向window,并且這段代碼在無(wú)意中創(chuàng)建了一個(gè)全局變量count,他的值為NaN。
那么,遇到這樣的問(wèn)題許多的開(kāi)發(fā)者(包括我),不會(huì)深入的思考為什么this的行為和預(yù)期的不一致,也不會(huì)回答那些很難解決,但非常重要的問(wèn)題。這里提供了三種解決這個(gè)問(wèn)題的方法,其中前兩種方法回避了this的含義和工作原理。代碼如下:
方法一 運(yùn)用作用域(詞法作用域)方法,該方法解決了我們遇到的問(wèn)題,但是卻沒(méi)有直面this。
function foo(num){ console.log("foo: " + num); data.count++; //記錄foo被調(diào)用的次數(shù) } var data ={ count: 0 }; for(var i=0; i<10; i++){ if(i > 5){ foo(i); } } // foo: 6 // foo: 7 // foo: 8 // foo: 9 console.log(data.count);// 4
方法二 創(chuàng)建一個(gè)指向函數(shù)對(duì)象的詞法標(biāo)識(shí)符(變量)來(lái)引用它。同樣該方法仍舊回避了this的問(wèn)題。
function foo(num){ console.log("foo: " + num); foo.count++; // foo指向它自身 } foo.count = 0; for(var i=0; i<10; i++){ if(i > 5){ foo(i); } } // foo: 6 // foo: 7 // foo: 8 // foo: 9 console.log(foo.count);// 4
方法三 既然我們知道this在foo函數(shù)執(zhí)行時(shí)指向了別處,那么我們需要做的就是強(qiáng)制this指向foo函數(shù).
function foo(num){ console.log("foo: " + num); this.count++; } foo.count = 0; for(var i=0; i<10; i++){ if(i > 5){ foo.call(foo, i); //使用call()可以確保this指向函數(shù)本身 } } // foo: 6 // foo: 7 // foo: 8 // foo: 9 console.log(foo.count);// 4
這次我們從this的角度解決了問(wèn)題。
誤解2.指向函數(shù)作用域第二種常見(jiàn)的誤解是:this指向函數(shù)作用域。這個(gè)問(wèn)題有點(diǎn)復(fù)雜,因?yàn)樵谀撤N情況下它是正確的,但在其他情況下他卻是錯(cuò)誤的。
但一定要明白,this在任何情況下都不指向函數(shù)的作用域,在javascript內(nèi)部作用域和對(duì)象確實(shí)很相似,可見(jiàn)的標(biāo)識(shí)符都是他的屬性,但作用域“對(duì)象”無(wú)法通過(guò)JavaScript代碼訪問(wèn),它存在于JavaScript引擎內(nèi)部
在文中給出了這樣一段代碼:
function foo(){ var a = 2; this.bar(); } function bar(){ console.log(this.a); } foo(); // ReferenceError: a is not defined
這段代碼試圖通過(guò)this聯(lián)通foo()和bar()的詞法作用域,從而讓bar()可以訪問(wèn)foo()作用域的變量a。but it"s impossible!
三、this到底是個(gè)什么玩意?通過(guò)排除以上種種的誤解,我們可以得出以下結(jié)論:
this是在運(yùn)行時(shí)進(jìn)行綁定的,并不是在編寫時(shí)綁定的。
this的綁定和函數(shù)聲明的位置沒(méi)有關(guān)系,只取決于函數(shù)的調(diào)用方式。
具體細(xì)節(jié)是:當(dāng)一個(gè)函數(shù)被調(diào)用時(shí),會(huì)創(chuàng)建一個(gè)活動(dòng)記錄(也稱執(zhí)行上下文(context))。這個(gè)記錄會(huì)包含一些信息,比如: 函數(shù)在哪里被調(diào)用(調(diào)用棧), 函數(shù)的調(diào)用方式, 傳入的參數(shù)等,而this就是這個(gè)記錄的一個(gè)屬性,會(huì)在函數(shù)執(zhí)行過(guò)程中被用到。
四、總結(jié)隨著你使用的模式越來(lái)越復(fù)雜,顯式傳遞上下文對(duì)象會(huì)讓代碼變得越來(lái)越混亂。因此,通過(guò)使用this隱式傳遞可以將API設(shè)計(jì)的更加簡(jiǎn)潔并且易于復(fù)用。
this既不指向函數(shù)自身,也不指向函數(shù)的作用域。
this實(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://systransis.cn/yun/78912.html
摘要:現(xiàn)在流行的前端框架都支持自定義組件,組件化開(kāi)發(fā)已經(jīng)成為提高前端開(kāi)發(fā)效率的銀彈。二對(duì)自定義組件的支持要想正確的渲染組件,第一步就是要告訴某個(gè)標(biāo)簽是自定義組件。下面的例子里,就是一個(gè)自定義組件。解決了識(shí)別自定義標(biāo)簽的問(wèn)題,下一步就是定義標(biāo)簽了。 歡迎關(guān)注我的公眾號(hào)睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、...
摘要:如果列表是空的,則存入組件后將異步刷新任務(wù)加入到事件循環(huán)當(dāng)中。四總結(jié)本文基于上一個(gè)版本的代碼,加入了事件處理功能,同時(shí)通過(guò)異步刷新的方法提高了渲染效率。 歡迎關(guān)注我的公眾號(hào)睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的兩大前端框架,React和Vue,都不約而同的借助Virtual DO...
摘要:本書(shū)屬于基礎(chǔ)類書(shū)籍,會(huì)有比較多的基礎(chǔ)知識(shí),所以這里僅記錄平常不怎么容易注意到的知識(shí)點(diǎn),不會(huì)全記,供大家和自己翻閱不錯(cuò),下冊(cè)的知識(shí)點(diǎn)就這么少,非常不推介看下冊(cè)上中下三本的讀書(shū)筆記你不知道的上讀書(shū)筆記你不知道的中讀書(shū)筆記你不知道的下讀書(shū)筆記第三 本書(shū)屬于基礎(chǔ)類書(shū)籍,會(huì)有比較多的基礎(chǔ)知識(shí),所以這里僅記錄平常不怎么容易注意到的知識(shí)點(diǎn),不會(huì)全記,供大家和自己翻閱; 不錯(cuò),下冊(cè)的知識(shí)點(diǎn)就這么少,非...
下一篇:《你不知道的javascript》筆記_對(duì)象&原型 寫在前面 上一篇博客我們知道詞法作用域是由變量書(shū)寫的位置決定的,那this又是在哪里確定的呢?如何能夠精準(zhǔn)的判斷this的指向?這篇博客會(huì)逐條闡述 書(shū)中有這樣幾句話: this是在運(yùn)行時(shí)進(jìn)行綁定的,并不是在編寫時(shí)綁定,它的上下文取決于函數(shù)調(diào)用時(shí)的各種條件this的綁定和函數(shù)聲明的位置沒(méi)有任何關(guān)系,只取決于函數(shù)的調(diào)用方式當(dāng)一個(gè)函數(shù)被調(diào)用時(shí)...
摘要:但是如果非全局的變量如果被遮蔽了,無(wú)論如何都無(wú)法被訪問(wèn)到。但是如果引擎在代碼中找到,就會(huì)完全不做任何優(yōu)化。結(jié)構(gòu)的分句中具有塊級(jí)作用域。第四章提升編譯器函數(shù)聲明會(huì)被提升,而函數(shù)表達(dá)式不會(huì)被提升。 本書(shū)屬于基礎(chǔ)類書(shū)籍,會(huì)有比較多的基礎(chǔ)知識(shí),所以這里僅記錄平常不怎么容易注意到的知識(shí)點(diǎn),不會(huì)全記,供大家和自己翻閱; 上中下三本的讀書(shū)筆記: 《你不知道的JavaScript》 (上) 讀書(shū)筆記...
摘要:的定義執(zhí)行上下文。這本書(shū)也是舉了好幾個(gè)例子來(lái)說(shuō)明,這句話的含義。我個(gè)人也認(rèn)為,不通過(guò)代碼,非常難說(shuō)明問(wèn)題。所以,修改的是全局的,并不是自身的。 this 先說(shuō)明一下,this是我JavaScript的盲區(qū),寫這篇文章,就是為了讓自己能重新認(rèn)識(shí)this,并且搞清楚,js里面的this,到底是什么。 這個(gè)系列主要是記錄我自己看《你不知道的JavaScript》這本書(shū)的筆記。 this的定義...
閱讀 2445·2021-11-22 13:53
閱讀 1135·2021-09-22 16:06
閱讀 1380·2021-09-02 15:21
閱讀 1911·2019-08-30 15:55
閱讀 3128·2019-08-29 11:19
閱讀 1926·2019-08-26 13:23
閱讀 947·2019-08-23 18:23
閱讀 1763·2019-08-23 16:06