如果你不知道什么是作用域,建議你先看什么是作用域鏈,什么是原型鏈。這篇文章,因為這些內容都是有關聯性的。
什么是自由變量?
如我在全局中定義了一個變量a,然后我在函數中使用了這個a,這個a就可以稱之為自由變量,可以這樣理解,凡是跨了自己的作用域的變量都叫自由變量。
var a = "追夢子"; function b(){ console.log(a); //追夢子 } b();
上面的這段代碼中的變量a就是一個自由變量,因為在函數b執行到console.log(a)的時候,發現在函數中找不到變量a,于是就往上一層中找,最后找到了全局變量a。
作用域的進階
在我講作用域鏈的時候說過如果有一個全局變量a,以及函數中也有一個變量a,那么只會作用函數中的那個變量a,都是有一種情況就顯得比較復雜一些,我們一起來看看這段代碼。
var aa = 22; function a(){ console.log(aa); } function b(fn){ var aa = 11; fn(); } b(a); //22
最后打印的不是11而是22,為什么會這樣呢?在我解釋之前我建議你事先看一下js中的執行上下文,菜鳥入門基礎。這一文,如果不了解js的執行順序就比較難以理解,另外如果你看了我這幾天的文章應該有種感覺,就是內容的關聯性都特別強,這也是為什么很多js新手朋友不能夠理解的地方。
我們接著說為什么打印的是22,一起來分析一下這段代碼。
假如我們的代碼是這樣的
var aa = 22; function a(){ console.log(aa); }
打印出的是22,我想大家應該沒有意見,但是有一點我一定要提,那就是在創建這個函數的時候,這個函數的作用域就已經決定了,而是不是在調用的時候,這句話至管重要。
有了這句話的基礎是不是理解上面的那段代碼就變得不值一提了?
為了照護新手朋友我還是分析一下過程吧。
首先我們創建了一個全局變量aa
var aa = 22;
接著我們創建了一個函數a
function a(){ console.log(aa); }
這時js解析這個函數的時候,就已經決定了這個函數a的作用域,既如果在函數a中找不到變量aa那就會到全局變量中找,如果找到了就返回這個aa,如果找不到就報錯。
接著我們又創建了一個函數b
function b(fn){ var aa = 11; fn(); }
在函數b中我們定義了又重新定義了這個變量aa,雖然我們這個時候重新定義了變量aa,但是因為函數a的作用域在創建的時候已經決定了,所以在函數b中創建的那個變量aa以及和函數a里面的那個變量aa沒有關系了。
function b(fn){ var aa = 11; fn(); } b(a);
我們把函數a傳到了函數b中,并且當做函數b的形參,接著我們執行了這個被傳進去的函數a,最后打印出來的就是22。
在創建這個函數的時候,這個函數的作用域就已經決定了,而是不是在調用的時候。
文章列表