標籤:

有關JS中作用域的問題,全局作用域中的變數不應該在全局變數對象中嗎,為什麼下面的函數搜索不到全局變數?

var a = "Hello";
function b() {
alert(a); //undefined
var a = "World";
alert(a);
}
b();

為什麼第一個alert輸出undefined呢?a不是全局變數嗎,在函數b的作用域鏈中包含了全局作用域啊,應該會去全局環境的變數對象中搜索到a變數啊,為啥會搜索不到呢?


JavaScript具有「聲明提升」的特性。使用function或var進行的聲明會被提升至當前作用域的頂端,因此你的代碼等價於下面這段:

var a = "Hello";
function b() {
var a;
alert(a); //undefined
a = "World";
alert(a);
}
b();


記得用v8的時候做逐行調試,當運行到一個新的context,其中var的變數就會顯示在scope中,值為undefined。也就是說,解釋引擎會首先執行聲明語句,這樣就覆蓋了scope外已經聲明的什麼全局變數、whatever。


當你的函數體內沒有給a重新賦值的時候,a確實是全局變數,因為函數內找不到,便會去全局作用域中找 a

var a = "Hello";
function b() {
alert(a);
}
b(); // Hello

但是你在函數中又給a重新賦值了,執行前解析器會先掃描整個函數,把所有申明的變數「提升」到函數頂部,所以函數內的a已經不是外面的那個a了,而在定義a前使用了a便是undefined。這換了其他的語言,會報 referened before assignment 錯誤,但是JavaScript並不會報錯,所以按照規範,最好先申明所有要用的變數。(當然如果a定義在使用之後,還是undefined)

```javascipt

var a = "Hello";
function b() {
var a;
a = " World!"
alert(window.a + a);
}
b();

```

window.a 才是全局的 a

函數也可以使用 window.b() 訪問,window代表全局的作用域,不過nodejs中沒有window


keyword: "hoisting", 不僅js會, python也會, 其他一些"解析性" 語言也會


javascript有預編譯過程,其中的函數會先執行,所以會出現上述過程。


推薦閱讀:

為什麼ECMAScript不原生支持重載?
這種所有圖片一直佔據100%寬度的響應式是如何做的?
有沒優雅的寫法,讓nodejs的回調+循環不那麼操蛋?
如何評判這篇文章說MVVM是一幫沒學好分層的搞出來的?
怎麼理解rxjs?

TAG:JavaScript |