當前位置:
首頁 > 知識 > 神奇的函數作用域

神奇的函數作用域

今天發現了兩個關於函數作用域的神奇例子,這裡和大家分享分享:

神奇的函數作用域

上面這段代碼在運行時會產生什麼結果?

我們來分析一下:

1.創建了全局變數 a,定義其值為 1

2.創建了函數 foo

3.在 foo 的函數體內,if 語句將不會執行,因為 !a 會將變數 a 轉變成布爾的假值,也就是 false

4.跳過條件分支,alert 變數 a,最終的結果應該是輸出 1

看起來無懈可擊的分析,但是實際上,結果錯誤。答案竟然是 2!為什麼?

什麼叫申明?

是指你聲稱某樣東西的存在,比如一個變數或一個函數;但你沒有說明這樣東西到底是什麼,僅僅是告訴解釋器這樣東西存在而已;

什麼叫定義?

是指你指明了某樣東西的具體實現,比如一個變數的值是多少,一個函數的函數體是什麼,確切的表達了這樣東西的意義。

所以上面的代碼實際上可以寫成這樣:

神奇的函數作用域

然後又有人會問,不是有個if嗎?if不成立哪就不會為a賦值為2。

因為 JavaScript 沒有塊級作用域(Block Scoping),只有函數作用域(Function Scoping),所以說不是看見一對花括弧 {} 就代表產生了新的作用域,和 C 不一樣!

當解析器讀到 if 語句的時候,它發現此處有一個變數聲明和賦值,於是解析器會將其聲明提升至當前作用域的頂部(這是默認行為,並且無法更改),這個行為就叫做 Hoisting。

怎樣能夠alert出那個a=1?

神奇的函數作用域

es6的語法,javascript是有塊級作用域的。

還可以通過閉包的方式實現:

神奇的函數作用域

第二個例子:

神奇的函數作用域

這個運行的結果是什麼?初略一看,alert(1),但是實際上報錯。

Uncaught TypeError: foo is not a function。

為什麼會這樣?

提升的僅僅是變數名 foo,至於它的定義依然停留在原處。因此在執行 foo() 之前,作用域只知道 foo 的命名,不知道它到底是什麼,所以執行會報錯(通常會是:undefined is not a function)。這叫做函數表達式(Function Expression),函數表達式只有命名會被提升,定義的函數體則不會。

神奇的函數作用域

怎麼改?

神奇的函數作用域

這個例子也展示了函數聲明與函數表達式的差別,函數申明會放到作用域的頂部,函數表達式則不會。

最後引用很多書中的一句話:「請始終保持作用域內所有變數的聲明放置在作用域的頂部」,相信現在的你對這句話應該有一個認識了。

文章摘自博客園


更多精彩推薦:

IT職業教育:http://www.ujiuye.com/

更多前端知識學習:http://www.ujiuye.com/zt/webqianduan/?wt.db=lsh11tt

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT優就業 的精彩文章:

CSS:transition過渡放在偽類中與應用的區別
自製刻度尺-前端簡易實現「信用」界面
Python垃圾回收機制 總結
js數組遍歷和對象遍歷

TAG:IT優就業 |

您可能感興趣

《函數項級數的基本概念、收斂域與解析性質》內容小結、題型與典型題
巧用WEB函數 輕鬆製作單詞表
函數奇偶性題型總結!
神經網路中常用的激活函數的說明
調用無參數的函數
利用導數研究含參函數的性質
向右操作符及其相關函數的基本用法
正弦函數究竟有多神奇?
在函數中調用函數
格林函數如何在凝聚態物理的量子場論中起作用?
遞歸函數及匿名函數配合內置函數的使用
5個適用於初學者的有用數據分析表達式函數
關於c語言中函數的調用的兩種方法
機器學習中常用的損失函數你知多少?
JS中把函數作為另一函數的參數傳遞方法(總結)
復用=高階函數和多態
工作中常用的十個函數公式,必須掌握
優化函數耗時的問題
如果一個函數作為另一個函數參數使用,那麼這函數叫做回調函數
密碼技術之單向散列函數