javascript執行上下文、作用域與閉包(第三篇)---自由變量與作用域鏈

首先解釋一下,什麼是自由變量。

在A作用域中使用的變量x,卻沒有在A作用域中聲明(即在其他作用域中聲明的),對於A作用域來說,x就是一個自由變量。簡單的說,凡是跨了自己的作用域的變量都叫自由變量。如:

var x=10;
function foo()
{
var b=20;
alert(x+b); //這裏x就是自由變量
}
foo();//30

在調用fn()函數時,函數體中第6行。取b的值就直接可以在fn作用域中取,因爲b就是在這裏定義的。而取x的值時,就需要到另一個作用域中取。到哪個作用域中取呢?

這時你可能就說,到上一級作用域去取值啊,(到上一級作用域裏取值就涉及到了作用域鏈的概念),但是這種說法是有歧義的,下面的例子就說明了這個歧義(爲什麼說是歧義呢?);

var aa = 22;
function a(){
    alert(aa);
}
function b(fn){
    var aa = 11;
    fn();
}
b(a); //22

按照一般思路來講,到上一級作用域取值,結果應該是11,爲什麼結果是22,而不是11呢?這就是這個歧義,不是說到上一級作用域取值有問題,而是到哪一個上一級作用域取值?

在上一篇 javascript執行上下文、作用域與閉包(第二篇)—作用域裏我有提到一個很重要的作用域的特點:作用域是在函數創建的時候就已經確定了,而不是函數調用的時候。

所以,在上面的例子裏函數a()的上一級作用域是全局作用域,而不是函數b()的作用域,故到上一級作用域取到的變量aa的值是22,而非11.

所以,我們要銘記:要到創建函數a()的那個作用域中取——而不管函數a()是在哪裏調用.

上面描述的只是上一級作用域就找到了變量,但是如果上一級作用域沒有找到了,那就再上一級,如果再沒有,就再上一級,直到全局作用域,如果全局作用域沒有,那就真的沒有了,並且,每上一級作用域取值都是到創建這個函數的作用域去取值。

所以我們可以看到,作用域鏈是因爲自由變量才存在的,也是因爲自由變量,作用域鏈纔有意義。

那麼,在結尾我再爲下一篇埋下一個伏筆,我們是真的在作用域裏取值嗎?

我們在上一篇說過,作用域只是一個範圍,裏面並沒有變量,其實是在作用域對應的執行上下文取值,可能同樣的作用域,相同的變量取到的值是不同的,那麼下一篇將會詳細講解作用域和執行上下文的關係。


下一篇: javascript執行上下文、作用域與閉包(第四篇)—作用域與執行上下文

本文參考了王福朋老師的深入理解javascript原型和閉包(14)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章