這兩本書都是很新的書,并且都是非常權威的書,強力推薦
特別是《你不知道的JavaScript》系列,上個月中卷剛出的時候我就迫不及待從網上買了一本
果然沒讓我失望
咳咳扯遠了,回到正題
我想原書的作者大神們,對于動態作用域的理解不一樣
所以才會造成這看似矛盾的觀點
在這里我想談談我的立場
通過我理解的,我也認為JavaScript中沒有動態作用域
關于靜態、動態作用域有什么區別
往下看↓
我先上一段代碼
function foo(){ var a = 1; bar(); }function bar(){ console.log(a); }var a = 100; foo();
通過我們對預編譯、作用域的深入理解
在我們JavaScript的詞法作用域中最后結果打印100
但是如果我們的作用域是動態作用域的話,打印的就變成了1
這是為什么呢?
詞法作用域最重要的特點就是它的定義過程發生在書寫階段(如果沒有使用eval()和with)
動態作用域使作用域在運行時被動態的確定
詞法作用域關心函數在何處聲明,作用域鏈基于作用域嵌套
動態作用域關心函數在何處調用,作用域鏈基于調用棧
我把上面的話翻譯到代碼上就是
詞法作用域:因為bar函數是在全局聲明的,所以我輸出全局的變量a的值
動態作用域:因為bar函數是在foo函數內調用的,所以我輸出foo內的變量a的值
這就是我的理解
我現在接觸過的程序語言有限,全部都是詞法作用域,我還沒見過基于動態作用域的語言
C、C++、C#、Java、JavaScript、php這些都是詞法作用域
其中JavaScript和php基于函數作用域,其他的基于塊作用域
在我的理解中
函數作用域就是函數代碼塊產生作用域,塊作用域就是大括號代碼塊產生作用域
看到很多博客中是這么寫的,JavaScript中只有函數作用域(大錯特錯)
這是完全不正確的,沒有爭議
JavaScript確實是基于函數作用域的,但不代表我們沒有塊作用域
特例還真不少,有with關鍵字、try-catch語句的catch子句、let關鍵字(ES6)、const關鍵字(ES6)
這里我只是簡單的說一下
關鍵字with和catch子句都可以產生塊作用域
這一點我在一篇文章中寫的應該是很詳細了
感興趣的同許多可以去看看
傳送門 –>JavaScript欺騙詞法的eval、with與catch及其性能問題
let關鍵字和var很像,都是聲明變量的,不過let關鍵字可以將變量綁定到所在的任意作用域中
而且使用let進行聲明不會在塊作用域中進行提升
const關鍵字同樣是聲明變量,不過它聲明的是常量,同樣綁定變量到塊作用域
這簡直和我們在C/C++的const關鍵字一樣
關于更多的我以后寫到ES6的知識時再詳細說吧
現在我們只需要知道“JavaScript中是有塊作用域的”就可以了
像平時一樣,給大家總結一下
作用域工作模式:詞法/靜態作用域,動態作用域
詞法作用域:函數作用域、塊作用域
JavaScript沒有動態作用域
JavaScript有塊作用域
with、catch子句、let(ES6)、const(ES6)產生塊作用域
詞法作用域關心函數在何處聲明
動態作用域關心函數在何處調用
詞法作用域作用域鏈基于作用域嵌套
動態作用域作用域鏈基于調用棧
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com