今天看了tom大叔的一篇文章 還有司徒正美的文章,其中講到一些關於javascript的小技巧的題,比較有趣,都有一些繞,不過很好理解。javascript
可是隻有一道題讓我琢磨半天,並非很難,可是從一開始分析方向就錯了,因此記錄下來分享。html
if (!("a" in window)) {
var a = 1;
}
console.log(a)
複製代碼
a
輸出什麼?一些老的javascript選手已經作出了答案,輸出是一個undefined
。但究竟爲何是undefined
呢?java
最開始我思考,由於Javascript沒有塊級做用域,因此if
裏面定義的var a = 1;
必定是會傳入到window對象裏面的,因此a
的輸出必定是1
。固然這道題不可能這麼簡單,想固然的就把這幾行代碼輸入到控制檯,輸出一下,發現輸出的是undefined
!ruby
赤裸裸的打臉讓我羞紅了臉龐,怎麼會這樣,難道 in
操做符有什麼詭異的操做嗎?趕忙搜了一下in操做符,趕忙查看一下,有沒有什麼鮮爲人知的js小技巧。函數
很快撇清了懷疑,由於並無關於操做符引起的詭異事件。既然如此,那必定是發生在window
和"a"
上面了!ui
爲了清晰的查看發生了什麼,我把var a
改爲了var b
,發現竟然奇蹟般地能夠輸出正確結果了。使人詫異的同時,也讓我發現了看來和裏面的 var a
有關,因而我定睛一看,發現並非 in
操做符的問題,而是 var
的問題spa
題目已經給出了答案,本題本質上是 var
帶來的變量提高code
// var a; 已經存在
if (!("a" in window)) {
//並無進到這裏
var a = 1;
} else {
//進入了這裏
}
console.log(a)
複製代碼
同時引出另外一個問題,最初忽略變量提高最大的緣由在於if (!("a" in window))
這句代碼,自己是一個判斷,a
是否存在於window
對象當中。所以,即便a === undefined
返回的也是true
。cdn
既然布爾值是true
,其實也就走不到var a = 1;
這一步了。這道題使人迷惑的緣由在於明明 if
語句沒能走下去,卻依然被var a = 1;
這句話帶來的影響而形成問題。htm
JavaScript 中,函數及變量的聲明都將被提高到函數的最頂部。
JavaScript 中,變量能夠在使用後聲明,也就是變量能夠先使用再聲明。
變量提高(Hoisting)被認爲是, Javascript中執行上下文 (特別是建立和執行階段)工做方式的一種認識。在 ECMAScript® 2015 Language Specification 以前的JavaScript文檔中找不到變量提高(Hoisting)這個詞。不過,須要注意的是,開始時,這個概念可能比較難理解,甚至惱人。
例如,從概念的字面意義上說,「變量提高」意味着變量和函數的聲明會在物理層面移動到代碼的最前面,但這麼說並不許確。實際上變量和函數聲明在代碼裏的位置是不會動的,而是在編譯階段被放入內存中。
因爲if
判斷語句存在 window
做用域下,所以變量提高依然生效,正由於沒有塊級做用域,因此存在於if
中的var
會提高到,window對象下。
如此說來本題也就解開了,一道由變量提高引起的謎題。最初卻被迷魂湯迷住了雙眼,正是因爲對if
判斷條件的信任才致使沒法理解代碼的走向。
這是一道很早以前的小題,咱們在平常寫代碼的時候通常也會格外注意做用域問題,並且大多數狀況不會使用in
來判斷。但假如真的須要使用,那就不得不注意變量提高致使的,in
操做符判斷的不肯定性,一道小題,幾分鐘迷人眼,但若是是一個大型組件,一時半會還真不那麼容易找到問題來源,浪費c幹不說,還讓代碼的不肯定性提高。