javascript
JavaScript 进阶(二)变量作用域
局部變量陷阱
先看一段代碼:
這個函數(shù)執(zhí)行完成之后返回helloworld,結(jié)果確實沒有問題。但是里面有一個細節(jié)就是兩個局部變量一個前邊有var,另一個沒有。這似乎并不影響執(zhí)行,但是事實上沒有var的話,這個變量就變成了全局變量。你在這個函數(shù)外面調(diào)用一下alert(b)試一下就知道了。一個莫名其妙冒出來的全局變量在有時候會引起匪夷所思的bug,所以一定要記得局部變量聲明前一定要用var
變量聲明提升
再看一段代碼:
代碼執(zhí)行時,請問alert的內(nèi)容是什么呢?答案是undefined。從直覺上來講,運行alert的時候,foo這個變量沒有聲明,不存在。既然局部作用域沒有,那就去全局作用域找,應(yīng)該是"hello"才是啊。為什么呢?這就是變量聲明提升。函數(shù)內(nèi)的任何變量的聲明都會被提升至函數(shù)的頂部,所以上面的test函數(shù)相當于
所以會是undefined。這里注意提升的只是聲明,賦值的代碼還在原來的地方。并且聲明的部分與聲明的代碼是否執(zhí)行無關(guān),比如
把test函數(shù)修改成這個樣子,執(zhí)行結(jié)果仍然是一樣。聲明仍然被提前了,盡管這行代碼將不會被運行。
這就是變量聲明提升,我們再看一個例子
當test函數(shù)執(zhí)行的時候,結(jié)果如何呢?結(jié)果是foo1被alert出來,然后JS報錯"undefined is not a function"。這里在函數(shù)內(nèi)部聲明函數(shù)的提升有點區(qū)別。foo1,用函數(shù)的方式聲明定義一個函數(shù),則聲明與函數(shù)體都被提升了,但是foo2用變量的方式定義函數(shù),被提升的只有聲明,函數(shù)體沒有被提升,所以執(zhí)行foo2()的時候,foo2沒有被賦值,是undefined。
看起來由于JS里面有變量聲明提升,那么就無法使用C語言里面的塊級作用域,那么我確實想用,怎么辦呢?有一個辦法是用匿名函數(shù),舉例如下:
當test函數(shù)改成這個樣子的時候,alert出來的結(jié)果就是"hello"了,匿名函數(shù)里面的foo就無法作用到其他地方。
閉包中的局部變量
我之前招聘前端,問了應(yīng)聘者這樣一個題目,說請寫一個可以返回遞增整數(shù)序列的函數(shù),他給我的答案是這樣
當反復(fù)調(diào)用函數(shù)increase的時候,就會返回遞增序列。但是我接著問,如果有人失手改了i怎么樣,他語塞。其實這個問題的關(guān)鍵是說要制造一個很安全的地方來放置這個i,讓這個變量只能被一個函數(shù)訪問,所以一個可選的答案是這樣。此時increase就是會返回遞增序列。并且i放在了一個很安全的地方。就不會被破壞了。
JS的閉包是一個很值得講的內(nèi)容,好用,但是也有不少坑,下面我專門開一篇文章來講。
全局變量
無數(shù)講高質(zhì)量代碼的書籍都會提到全局變量這個大殺器,程序員們都被反復(fù)告誡,除非你又充足的理由,否則不要使用全局變量,JS也不例外。然而JS有一個特殊的地方就是沒有main方法,入口的代碼一定要寫,但是寫在這地方的代碼難免要用到變量,這些變量就是全局變量了,那么如何處理這個問題呢?答案還是匿名函數(shù),像這樣:
把入口代碼放到一個匿名函數(shù)中,這樣這些變量a, b, c就會被藏到這個函數(shù)里面,就避免了全局變量的出現(xiàn)。
總結(jié)
以上是生活随笔為你收集整理的JavaScript 进阶(二)变量作用域的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小米13 Ultra手机壳曝光:中分四摄
- 下一篇: JavaScript getFullYe