自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

js 作用域鏈&內存回收&變量&閉包

開發(fā) 前端
閉包主要涉及到js的幾個其他的特性:作用域鏈,垃圾(內存)回收機制,函數(shù)嵌套,等等

閉包主要涉及到js的幾個其他的特性:作用域鏈,垃圾(內存)回收機制,函數(shù)嵌套,等等

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

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

三、局部變量&全局變量

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

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

3、

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

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

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

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

function a(x,y){

     var b=x+y;

     return b;

}

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

var tatal=a(5,10);

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

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

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

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

保存在棧內存中的每個值,分別占據著固定大小的空間,可以按照順序來訪問它們。如果棧內存中保存的是一塊內存的地址,則這個值就像是一個指向對象在堆內存中位置的指針。保存在堆內存中的數(shù)據不是按順序訪問的,因為每個對象所需要的空間并不相等。

當從一個變量向另一個變量復制引用類型的值時,同樣也會將儲存在棧中的值復制一份放到為新變量分配的空間中。不同的是,這個值的副本實際上是一個指針,而這個指針指向存儲在堆中的一個對象。復制操作結束后,兩個變量實際上將引用同一個對象。因此,改變其中一個變量,就會影響到另一個變量。

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

四、閉包

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

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

 

使用閉包的注意點

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

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

閉包一些例子:

責任編輯:王雪燕 來源: 博客園
相關推薦

2011-05-12 18:26:08

Javascript作用域

2017-09-14 13:55:57

JavaScript

2020-12-16 11:09:27

JavaScript語言開發(fā)

2021-03-09 08:35:51

JSS作用域前端

2021-12-06 07:15:48

Javascript作用域閉包

2016-12-19 11:10:32

JavaScript變量作用域

2020-11-19 07:49:24

JS變量作用域

2021-06-02 07:02:42

js作用域函數(shù)

2011-09-06 09:56:24

JavaScript

2019-03-13 08:00:00

JavaScript作用域前端

2011-04-18 09:31:35

JavaScript

2013-09-05 10:07:34

javaScript變量

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2016-10-31 20:56:57

Javascript閉包內存泄漏

2021-03-16 22:25:06

作用域鏈作用域JavaScript

2020-08-11 09:47:30

JS閉包代碼

2010-01-07 16:16:03

VB.NET變量作用域

2021-10-28 10:26:35

Javascript 高階函數(shù)前端

2024-01-22 09:51:32

Swift閉包表達式尾隨閉包

2023-11-26 00:34:36

Javascript應用方法
點贊
收藏

51CTO技術棧公眾號