JavaScript 之 作用域、閉包

作用域

全局作用域:

??????? 如果變量的作用域是全局的,就意味著該變量可以在任何的位置被訪問到。不單獨屬于某一個函數的變量就是一個全局變量,在任何位置都(普通函數中、構造函數中、字面量對象中)可以訪問到這個變量。

局部作用域:

?????? 在函數中定義的變量作用域是局部的,該變量只能在當前作用域中和內部嵌套的作用域中訪問到,在上級作用域和其他的兄弟級作用域中無法訪問。

?????? 在函數中使用var定義的變量是局部變量。

????? 注意:在js中塊級(也就是大括號)的概念并不像其他語言那樣完善(ECMAScript6中完善了這個概念),在其他語言中,一對大括號中的變量就是一個局部變量,但是在js中只有在一個函數中定義的變量才是一個局部變量。即在js語言中,沒有‘塊級’的概念。

?????? 什么是塊級?

????? 在其他語言中,一組大括號包裹的范圍就是塊級,我們可以使用塊級來確定一個變量的作用域范圍。但在js中,沒有塊級的概念,所以只能使用函數來確定一個作用域的范圍。

?????? eg.

????????? vara = 12;

?????????? for(var i = 0; i < 5; i++) {

??????????????? var a = i;//此處的a因為和外部的a同處于全局作?用域,所以會覆蓋外部的a

??????????? }

?????????? alert(a);// 4

作用域鏈

??????? JS中的變量查詢的一種機制。在某個位置訪問某個變量時,如果當前作用域中沒有定義該變量,則啟動作用域鏈,向上級作用域查詢,一直查詢到全局作用域,如果在某一級中找到該變量,就會輸出;沒有找到,就報錯:變量未定義(not defined)。

1、undefined:在只定義了變量但是沒有給變量賦值的情況下,訪問該變量。結果就是undefined(一個已定義的變量標準是:

??????? 1>、在內存中開辟內存空間;

??????? 2>、數據類型確定。js中定義變量時開辟內存空間,而確定變量類型是由賦值的類型確定的)

這樣輸出的結果均是button3

解決方案:


2、變量提升機制

??????? 在js代碼正式執行之前,會把當前作用域中的所有定義操作先執行起來,等真正的執行到了相關定義并賦值變量的代碼時,才真正的給變量賦上值。變量提升提升的是當前作用域中的所有定義操作(包括定義變量、定義對象、定義函數、定義數組......)

???? eg.

匿名函數

?概念:

??????? 沒有函數名字的函數是匿名函數,區分:具名函數,有函數名的函數

匿名函數的執行方式?

1>、通過實踐調用執行

?????????? 例如:通過事件調用執行

2>、通過變量名:把匿名函數賦給一個變量來執行?


3>、通過定時器等系統函數執行

4>、函數自調用執行

匿名函數的使用場景?

1>、把函數當做事件函數時,使用匿名函數

2>、把函數當做另一個函數的參數時,使用匿名函數(定時器)


3>、把函數當做另一個函數的返回值時,使用匿名函數(閉包)

創建一個匿匿名函數

閉包

?????? 概念:閉包能夠讀取其他函數內部變量。

? ? ? 閉包就是函數的局部變量集合,只是這些局部變量在函數返回后會繼續存在。

? ? ? 閉包就是就是函數的“堆棧”在函數返回后并不釋放,我們也可以理解為這些函數堆棧并不在棧上分配而是在堆上分配。

? ? ? 當在一個函數內定義另外一個函數就會產生閉包。

閉包的用途:

???? 1>、可以在全局作用域讀取函數內部的變量

???? 2>、讓這些局部變量的值始終保持在內存中。

???? 3>、通過閉包模擬一個塊級作用域

???? 4>、利用閉包解決使用循環添加事件的Bug

??????????? eg. 全局作用域讀取局部變量的示例

???????????? 注:

??????????????? f1是f2的父函數,而f2被賦給了一個全局變量,這導致f2始終在內存中,而f2的存在依?? 賴于f1,因此f1也始終在內存中,不會在調用結束后,被垃圾回收機制(garbage collection)回收。


資料:伯樂在線。 http://web.jobbole.com/89134/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容