怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包

本篇內(nèi)容介紹了“怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

成都創(chuàng)新互聯(lián)主要從事做網(wǎng)站、成都網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)湖里,10年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):18980820575

一、作用域鏈:函數(shù)在定義的時(shí)候創(chuàng)建的,用于尋找使用到的變量的 值的一個(gè)索引,而他內(nèi)部的規(guī)則是,把函數(shù)自身的本地變量放在最前面,把自身的父級(jí)函數(shù)中的變量放在其次,把再高一級(jí)函數(shù)中的變量放在更后面,以此類推直至 全局對(duì)象為止.當(dāng)函數(shù)中需要查詢一個(gè)變量的值的時(shí)候,js解釋器會(huì)去作用域鏈去查找,從最前面的本地變量中先找,如果沒(méi)有找到對(duì)應(yīng)的變量,則到下一級(jí)的鏈 上找,一旦找到了變量,則不再繼續(xù).如果找到***也沒(méi)找到需要的變量,則解釋器返回undefined。

二、內(nèi)存回收機(jī)制:一個(gè)函數(shù)在執(zhí)行開(kāi)始的時(shí)候,會(huì)給其中定義的變 量劃分內(nèi)存空間保存,以備后面的語(yǔ)句所用,等到函數(shù)執(zhí)行完畢返回了,這些變量就被認(rèn)為是無(wú)用的了.對(duì)應(yīng)的內(nèi)存空間也就被回收了.下次再執(zhí)行此函數(shù)的時(shí)候, 所有的變量又回到最初的狀態(tài),重新賦值使用.但是如果這個(gè)函數(shù)內(nèi)部又嵌套了另一個(gè)函數(shù),而這個(gè)函數(shù)是有可能在外部被調(diào)用到的.并且這個(gè)內(nèi)部函數(shù)又使用了外 部函數(shù)的某些變量的話.這種內(nèi)存回收機(jī)制就會(huì)出現(xiàn)問(wèn)題.如果在外部函數(shù)返回后,又直接調(diào)用了內(nèi)部函數(shù),那么內(nèi)部函數(shù)就無(wú)法讀取到他所需要的外部函數(shù)中變量 的值了.所以js解釋器在遇到函數(shù)定義的時(shí)候,會(huì)自動(dòng)把函數(shù)和他可能使用的變量(包括本地變量和父級(jí)和祖先級(jí)函數(shù)的變量(自由變量))一起保存起來(lái).也就 是構(gòu)建一個(gè)閉包,這些變量將不會(huì)被內(nèi)存回收器所回收,只有當(dāng)內(nèi)部的函數(shù)不可能被調(diào)用以后(例如被刪除了,或者沒(méi)有了指針),才會(huì)銷毀這個(gè)閉包,而沒(méi)有任何 一個(gè)閉包引用的變量才會(huì)被下一次內(nèi)存回收啟動(dòng)時(shí)所回收。

三、局部變量&全局變量

1、全局(global)變量的作用域是全局的,在Javascript中處處有定義;而函數(shù)內(nèi)部聲明的變量是局部(local)變量,其作用域是局部性的,只在函數(shù)體內(nèi)部有定義,每次執(zhí)行該函數(shù)時(shí)都會(huì)創(chuàng)建和破壞該變量。

2、全局變量作用域中使用變量可以不用var語(yǔ)句,但在聲明局部變量是一定要使用var語(yǔ)句,否則會(huì)視為對(duì)全局變量的引用。

3、

怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包

var scope = "local";聲明的變量在整個(gè)checkScope函數(shù)作用域內(nèi)都有效,因此***個(gè)document.write(scope);執(zhí)行的時(shí)scope引用的是局部變量,而此時(shí)局部變量scope尚未定義,所以輸出”undefined”。好的編程習(xí)慣是將所有的變量聲明集中起來(lái)放在函數(shù)的開(kāi)頭。document.write(window.scope)//輸出global

全局變量總是存在于運(yùn)行期上下文作用域鏈的最末端,因此在標(biāo)識(shí)符解析的時(shí)候,查找全局變量是最慢的。所以,在編寫代碼的時(shí)候應(yīng)盡量少使用全局變 量,盡可能使用局部變量。一個(gè)好的經(jīng)驗(yàn)法則是:如果一個(gè)跨作用域的對(duì)象被引用了一次以上,則先把它存儲(chǔ)到局部變量里再使用(document、 window等)。

在執(zhí)行JavaScript代碼的過(guò)程中,當(dāng)遇到一個(gè)標(biāo)識(shí)符,就會(huì)根據(jù)標(biāo)識(shí)符的名稱,在執(zhí)行上下文(Execution  Context)的作用域鏈中進(jìn)行搜索。從作用域鏈的***個(gè)對(duì)象(該函數(shù)的Activation  Object對(duì)象)開(kāi)始,如果沒(méi)有找到,就搜索作用域鏈中的下一個(gè)對(duì)象,如此往復(fù),直到找到了標(biāo)識(shí)符的定義。如果在搜索完作用域中的***一個(gè)對(duì)象,也就是 全局對(duì)象(Global  Object)以后也沒(méi)有找到,則會(huì)拋出一個(gè)錯(cuò)誤,提示用戶該變量未定義(undefined)。這是在ECMA-262標(biāo)準(zhǔn)中描述的函數(shù)執(zhí)行模型和標(biāo)識(shí) 符解析(Identifier Resolution)的過(guò)程。

由ECMA-262標(biāo)準(zhǔn)第三版定義,該內(nèi)部屬性包含了函數(shù)被創(chuàng)建的作用域中對(duì)象的集合,這個(gè)集合被稱為函數(shù)的作用域鏈,它決定了哪些數(shù)據(jù)能被函數(shù)訪問(wèn)。作用域***個(gè)對(duì)象始終是當(dāng)前執(zhí)行代碼所在環(huán)境的變量對(duì)象

function a(x,y){

var b=x+y;

return b;

}

在函數(shù)a創(chuàng)建的時(shí)候它的作用域鏈填入全局對(duì)象,全局對(duì)象中有所有全局變量

怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包

var tatal=a(5,10);

執(zhí)行此函數(shù)時(shí)會(huì)創(chuàng)建一個(gè)稱為“運(yùn)行期上下文(execution  context)”的內(nèi)部對(duì)象,運(yùn)行期上下文定義了函數(shù)執(zhí)行時(shí)的環(huán)境。值按照它們出現(xiàn)在函數(shù)中的順序被復(fù)制到運(yùn)行期上下文的作用域鏈中。它們共同組成了一 個(gè)新的對(duì)象,叫“活動(dòng)對(duì)象(activation  object)”,該對(duì)象包含了函數(shù)的所有局部變量、命名參數(shù)、參數(shù)集合以及this,然后此對(duì)象會(huì)被推入作用域鏈的前端,當(dāng)運(yùn)行期上下文被銷毀,活動(dòng)對(duì) 象也隨之銷毀。

怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包

ECMAScript變量可能包含兩種不同數(shù)據(jù)類型的值:基本類型值和引用類型值?;绢愋椭抵傅氖悄切┍4嬖跅?nèi)存中的簡(jiǎn)單數(shù)據(jù)段,即這種值 完全  保存在內(nèi)存中的一個(gè)位置。而引用類型值是指那些保存堆內(nèi)存中的對(duì)象,意思是變量中保存的實(shí)際上只是一個(gè)指針,這個(gè)指針指向內(nèi)存中的另一個(gè)位置,該位置保存 對(duì)象。

5種基本數(shù)據(jù)類型:Undefined、Null、Boolean、 Number和String。這5種基本數(shù)據(jù)類型的值在內(nèi)存中分別占有固定大小的空間,因此可以把它們的值保存在棧內(nèi)存。

如果賦給變量的是一個(gè)引用類型的值,則必須在堆內(nèi)存中為這個(gè)值分配空間。由于這種值的大小不固定,因此不能把它們保存到棧內(nèi)存中。但內(nèi)存地址的 大小  是固定的,因此可以將內(nèi)存地址保存在棧內(nèi)存中。這樣,當(dāng)查詢引用類型的變量時(shí),就可以首先從棧中讀取內(nèi)存地址,然后再“順藤摸瓜”地找到保存在堆中的值。

保存在棧內(nèi)存中的每個(gè)值,分別占據(jù)著固定大小的空間,可以按照順序來(lái)訪問(wèn)它們。如果棧內(nèi)存中保存的是一塊內(nèi)存的地址,則這個(gè)值就像是一個(gè)指向?qū)ο笤诙褍?nèi)存中位置的指針。保存在堆內(nèi)存中的數(shù)據(jù)不是按順序訪問(wèn)的,因?yàn)槊總€(gè)對(duì)象所需要的空間并不相等。

當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型的值時(shí),同樣也會(huì)將儲(chǔ)存在棧中的值復(fù)制一份放到為新變量分配的空間中。不同的是,這個(gè)值的副本實(shí)際上是一個(gè)指針,而這個(gè)指針指向存儲(chǔ)在堆中的一個(gè)對(duì)象。復(fù)制操作結(jié)束后,兩個(gè)變量實(shí)際上將引用同一個(gè)對(duì)象。因此,改變其中一個(gè)變量,就會(huì)影響到另一個(gè)變量。

typeof操作符是確定一個(gè)變量是字符串、數(shù)值、布爾 值,還是undefined基本數(shù)據(jù)類型的***工具。檢測(cè)引用類型的值時(shí),ECMAScript提供了instanceof操作符。

四、閉包

只要存在調(diào)用內(nèi)部函數(shù)的可能,JavaScript就需要保留被引用的函數(shù)。而且JavaScript運(yùn)行時(shí)需要跟蹤引用這個(gè)內(nèi)部函數(shù)的所有變量,直到***一個(gè)變量廢棄,JavaScript的垃圾收集器才能釋放相應(yīng)的內(nèi)存空間(紅色部分是理解閉包的關(guān)鍵)。

閉包***用處有兩個(gè),一個(gè)是可以讀取函數(shù)內(nèi)部的變量,另一個(gè)就是讓這些變量的值始終保持在內(nèi)存中。

怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包

使用閉包的注意點(diǎn)

1)由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會(huì)造成網(wǎng)頁(yè)的性能問(wèn)題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。

2)閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對(duì)象(object)使用,把閉包當(dāng)作它的公用方法(Public  Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時(shí)一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。

閉包一些例子:

怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包

怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包

“怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

網(wǎng)頁(yè)名稱:怎么掌握js作用域鏈、內(nèi)存回收、變量、閉包
網(wǎng)站URL:http://muchs.cn/article30/gdopso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、網(wǎng)站設(shè)計(jì)公司、小程序開(kāi)發(fā)、微信小程序、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司