1、变量提升
?
前言
hoist
vt.升起,提起;
vi.被舉起或抬高;
n.起重機,升降機; 升起; <俚>推,托,舉;
這篇文章不講英語,但是對于某些英語單詞找不到很好的翻譯,一上來就列出“hoist”這個單詞的釋義是為了讓大家有個準備,我在這里將此單詞翻譯為“提前”,是為了解釋 JavaScript 語言中很“古怪”的一個特性。
?
?
變量聲明“被提前”
JavaScript 的語法和 C 、Java、C# 類似,統稱為 C 類語法。有過 C 或 Java 編程經驗的同學應該對“先聲明、后使用”的規則很熟悉,如果使用未經聲明的變量或函數,在編譯階段就會報錯。然而,JavaScript 卻能夠在變量和函數被聲明之前使用它們。下面我們就深入了解一下其中的玄機。
運行下邊代碼立馬就報錯,不過,這也正是我們期望的,因為 x 變量根本就沒有定義過嘛!
console.log(x);?[Web瀏覽器] "Uncaught ReferenceError: x is not defined"
?
再來看看下面的代碼,x?變量是在調用語句后面定義,為什么居然輸出的是 undefined呢?!
這其實是 JavaScript 解析器搞的鬼,解析器將當前作用域內聲明的所有變量和函數都會放到作用域的開始處,但是,只有變量的聲明被提前到作用域的開始處了,而賦值操作被保留在原處。
上述代碼對于解析器來說其實是如下這個樣子滴,備注里是重點。
這就是為什么上述代碼不報異常的原因!變量和函數經過“被提前”之后,x變量其實就被放在了調用函數的前面,根據 JavaScript 語法的定義,已聲明而未被賦值的變量會被自動賦值為 undefined ,所以,打印 x變量的值就是 undefined
?[Web瀏覽器] "undefined"
?
其實這種影響還蠻煩人的,比如:
我們先聲明了一個變量 x ,我們的本意是希望在第一次打印 name 變量時能夠輸出全局范圍內定義的 x 變量,然后再在函數中定義一個局部 x 變量覆蓋全局變量,最后輸出局部變量的值。可是第一次輸出的結果和我們的預期完全不一致,原因就是我們定義的局部變量在其作用域內被“提前”了,也就是變成了如下形式:
[Web瀏覽器] "undefined"
[Web瀏覽器] "456"
?
后語
由于 JavaScript 具有這樣的“怪癖”,所以你會看到很多編碼指南建議大家將變量聲明放在作用域的最上方,這樣就能時刻提醒自己注意了。
?
?
參考:
http://www.bootcss.com/article/variable-and-function-hoisting-in-javascript/
轉載于:https://www.cnblogs.com/dshvv/p/5453314.html
總結
- 上一篇: [工作积累] shadow map问题汇
- 下一篇: Python之实现一个简易计算器