以下程式碼:
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 不只是局部和全局聲明的區別?
新手求教,謝謝!
程式碼執行總有個先後順序吧。 。 。
補充一點:
直接
b = 2
这种创建全局变量的方式,其实质是变为全局对象上的一个属性,即window.b = 2
,所以,這不存在什麼提升不提升;使用var聲明的變數則存在聲明提升。自己再自問自答補充一點:
在 mdn 查到這樣一句話:
這句話解釋了我關於全域變數 b 為什麼不會像 a 一樣提升的困惑。 a 是宣告變量,而 b 是非宣告變量,只有在執行時才會定義,所以不會在執行前提升。
原文:https://developer.mozilla.org...
聲明會提前
會被編譯器解釋成
而 未聲明/未定義 則連被提升的機會都沒有, 所以一用就報錯
這些作用域的問題 你可以看看 《你不知道的javascript》(上卷) 上面都有講到
引擎---
從頭到尾負責整個JavaScript程式的編譯及執行過程。
編譯器---
引擎的朋友,負責語法分析及程式碼產生的工作。
作用域---
引擎的另一個朋友,負責收集並維護由所聲明的標識符(變量)組成的一系列查詢,並實施一套非常嚴格的規則,確定當前執行的代碼對這些標識符的存取權限。
當你看到var a = 1;
事實上,引擎認為這裡有兩個完全不同的聲明,一個由編譯器在編譯時處理,另一個由引擎在運行時處理。
var a=1;分解
遇到var a,編譯器會詢問作用域是否已經有一個該名稱的變數存在於同一個作用域的集合中。如果是,編譯器會忽略該聲明,繼續進行編譯;否則他會要求作用域在目前作用域的集合中聲明一個新的變量,並命名為a。
接下來編譯器會為引擎產生運行時所需要的程式碼,這些程式碼被用來處理a=1這個賦值運算。引擎運作時首先詢問作用域,在目前的作用域集合中是否存在一個叫做a的變量,如果是,引擎就會使用這個變數;如果否,引擎就會繼續尋找該變數。