標籤:一個 define def func script 聲明變數 str efi 利用
承接上一篇博文的總結,這篇博文是利用代碼+畫圖的形式,梳理一下對於函數範圍和閉包的理解。
函數中的範圍
在 JavaScript 中, 對象和函數同樣也是變數。
在 JavaScript 中, 範圍為可訪問變數,對象,函數的集合。
首先我們聲明一個函數,然後在函數內部聲明並賦值一個變數:
function fn(){ var x = 3 console.log(x)}fn.call() //3
在函數fn中就產生了一個範圍,要求列印x的值時,函數就會在自身內部尋找這個x,然後把結果打出來。
在函數內部再次聲明一個函數的話,情況會變成什麼樣呢:
function fn(){ var x = 3 // console.log(x) function fn1(){ var x = 4 console.log(x) } fn1.call()}fn.call() //4
函數fn1在fn範圍內創造了一個子範圍,列印的時候不使用fn中的變數x,而是使用了這個子範圍內的變數x。
如果fn1中沒有聲明變數x,他會列印出什麼呢?
function fn(){ var x = 3 function fn1(){ console.log(x) } fn1.call()}fn.call() //3
他會去尋找fn中的x,然後把他列印出來。
如果函數fn範圍內也不存在這個變數呢?
var x = 5function fn(){ function fn1(){ console.log(x) } fn1.call()}fn.call() //5
由此可以看出:在調用函數範圍(fn1)中的某個變數(x)時,他會先在自身範圍中尋找這個變數;如果這個變數沒有找到,那麼這個函數可以訪問上一級範圍(fn)中的變數(x);如果這個變數還沒有找到,那麼這個函數可以訪問更上一級,即全域範圍(window)中的x。
注意
在理解範圍的同時,我們要十分注意變數提升的問題。
比如:
function fn(){ function fn1(){ console.log(x) var x = 5 } fn1.call()}fn.call() //undefined
為什麼會列印出了undefined呢?
因為這段代碼實際上表達的意思是這樣:
function fn(){ function fn1(){ var x console.log(x) x = 5 } fn1.call()}fn.call() //undefined
變數x只是做出了聲明,但是並沒有賦值,所以列印出來是undefined。
閉包
既然理解了函數範圍,就能理解閉包了。
「函數」和「函數內部能訪問到的變數」(也叫環境)的總和,就是一個閉包。
比如上文這張圖:
函數fn1加上他可以訪問的位於函數fn的範圍內的變數x,就是一個閉包。
關於閉包的更詳細的解釋,可以看看方應杭方老師的這篇文章,我們充分理解,學以致用,就可以了。
[JavaScript]JavaScript中的函數(2)