JavaScript 全域變數的一個困惑
ringa_lee
ringa_lee 2017-05-18 10:56:05
0
5
607

以下程式碼:

console.log(b);
b = 2;
//"ReferenceError: b is not defined

我以為印出來會是 undefined。
按我的理解 b = 2 沒有使用 var,所以是聲明了一個全域變量,既然聲明了變量,那就會有變量聲明提升,為什麼會是ReferenceError: b is not defined 呢?

而嘗試加上 var:

console.log(b);
var b = 2;
//undefined

所以這樣看來 用 var 和省略 var 不只是局部和全局聲明的區別?
新手求教,謝謝!

ringa_lee
ringa_lee

ringa_lee

全部回覆(5)
刘奇
// ①
console.log(b); // 代码执行到这行的时候,b未定义,在当前的作用域链上找不到b,所以 b is not defined
b = 2; 

// ②
console.log(b);
var b = 2;
// 由于变量声明提升,相当于
var b;
console.log(b); // 代码执行到这行的时候,b已经声明了,只是没有赋值而已,所以 undefined
b = 2; 

程式碼執行總有個先後順序吧。 。 。

補充一點:
直接b = 2这种创建全局变量的方式,其实质是变为全局对象上的一个属性,即window.b = 2,所以,這不存在什麼提升不提升;使用var聲明的變數則存在聲明提升。

刘奇

自己再自問自答補充一點:

在 mdn 查到這樣一句話:

宣告變數在任何程式碼執行前創建,而非宣告變數只有在執行賦值操作的時候才會被創建。

這句話解釋了我關於全域變數 b 為什麼不會像 a 一樣提升的困惑。 a 是宣告變量,而 b 是非宣告變量,只有在執行時才會定義,所以不會在執行前提升。

原文:https://developer.mozilla.org...

某草草

聲明會提前

console.log(a);
var a = 1;

會被編譯器解釋成

var a;
console.log(a);
a = 1;

而 未聲明/未定義 則連被提升的機會都沒有, 所以一用就報錯

伊谢尔伦

這些作用域的問題 你可以看看 《你不知道的javascript》(上卷) 上面都有講到

刘奇
  • 引擎---
    從頭到尾負責整個JavaScript程式的編譯及執行過程。

  • 編譯器---
    引擎的朋友,負責語法分析及程式碼產生的工作。

  • 作用域---
    引擎的另一個朋友,負責收集並維護由所聲明的標識符(變量)組成的一系列查詢,並實施一套非常嚴格的規則,確定當前執行的代碼對這些標識符的存取權限。

當你看到var a = 1;
事實上,引擎認為這裡有兩個完全不同的聲明,一個由編譯器在編譯時處理,另一個由引擎在運行時處理。
var a=1;分解

  1. 遇到var a,編譯器會詢問作用域是否已經有一個該名稱的變數存在於同一個作用域的集合中。如果是,編譯器會忽略該聲明,繼續進行編譯;否則他會要求作用域在目前作用域的集合中聲明一個新的變量,並命名為a。

  2. 接下來編譯器會為引擎產生運行時所需要的程式碼,這些程式碼被用來處理a=1這個賦值運算。引擎運作時首先詢問作用域,在目前的作用域集合中是否存在一個叫做a的變量,如果是,引擎就會使用這個變數;如果否,引擎就會繼續尋找該變數。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板