JavaScript做用域 - 學習Javascript的基石之一(轉)

1.做用域 函數

JavaScript的做用域與C、Java等語言不一樣,它不是以花括號包圍的塊級做用域,這個特性常常被大多數人忽視。例以下面代碼,在大多數類C的語言中會出現變量未定義的錯誤,但在JavaScript中卻徹底合法: spa

if (true) {
    var msg = 'msg';
}
console.log(msg); // 輸出 msg;

這是由於JavaScript的做用域徹底是由函數來決定的,if、for語句中的花括號不是獨立的做用域。 code

2.函數做用域 ip

不一樣於大多數類C的語言,由一對花括號封閉的代碼塊就是一個做用域,JavaScript的做用域是經過函數來定義的,在一個函數中定義的變量只對這個函數內部可見,咱們稱爲函數做用域。在函數中引用一個變量時,JavaScript會先搜索當前函數做用域,若是沒有找到則搜索其上層做用域,一直到全局做用域。下面是一個簡單的例子: 作用域

var scope = 'global';
var f1 = function() {
    console.log(scope);
}
f1(); // 輸出 global

var f2 = function() {
    var scope = 'f2';
    console.log(scope);
}
f2(); // 輸出 f2

以上示例十分明瞭,JavaScript的函數定義是能夠嵌套的,每一層是一個做用域,變量搜索順序是從內到外,按照做用域搜索順序,在console.log函數訪問scope變量時,JavaScript會先搜索函數f2的做用域,恰巧在f2的做用域裏搜索到了scope變量,因此上層做用域中定義的scope就被屏蔽了。但下面這個例子可能就有些讓人困惑: io

var scope = 'global';
var f3 = function() {
    console.log(scope);
    var scope = 'f3';
}
f3(); // 輸出 undefined

上面的代碼可能和你的預想不同,並無輸出global,而是undefined,這是爲何吶?這是JavaScript的一個特性,就是變量聲明語句永遠在該做用域裏最早被執行,因此上面的例子形同以下: console

var scope = 'global';
var f4 = function() {
    var scope; // 變量聲明最早被執行
    console.log(scope);
    scope = 'f4'; //變量被賦予值
}
f4(); // 輸出 undefined

這樣就不難理解運行f3()函數爲何沒輸出global,而是undefined了。 function

3.函數做用域的嵌套 class

一個做用域嵌套的例子: 變量

var f5 = function() {
    var scope = 'first';
    (function() {
        var scope = 'second';
        (function() {
            console.log(scope);
        }());
    }());
}
f5(); // 輸出 second

咱們在最內層函數中引用到了scope變量,經過做用域搜索,找到了其父做用域中定義的scope變量。

有一點要注意:函數做用域的嵌套關係是在定義時決定的,而不是在調用時決定的,下面是一個簡單的例子:

var scope = 'global';
var f6 = function() {
    console.log(scope);
}
var f7 = function() {
    var scope = 'f7';
    f6();
}
f7(); // 輸出 global

這個例子中,經過f7調用的f6在搜索scope時,找到的是f6函數的父做用域中定義的scope變量,而不是f7中定義的scope變量。這說明了函數做用域的嵌套關係是在定義時決定的,而不是在調用時決定的。

相關文章
相關標籤/搜索