做用域是指程序源代碼中定義變量的區域。javascript
做用域規定了如何查找變量,也就是肯定當前執行代碼對變量的訪問權限。java
JavaScript 採用詞法做用域,也就是靜態做用域。git
由於Javascript採用的是詞法做用域,因此它的函數的做用域在函數定義的時候就決定了。github
而與詞法做用域相對的是動態做用域,它的函數的做用域是在函數調用的時候才決定的。bash
讓咱們認真看個例子就能明白以前的區別:函數
var value = 1; function foo(){ console.log(value) } function bar(){ var value = 2; foo(); } bar(); // 結果是?
假設javascript採用靜態做用域,讓咱們分析下執行過程:spa
執行foo函數,先從foo函數內部查找是否有局部變量value,若是沒有,就根據書寫的位置,查找上面一層的代碼,也就是value等於1,因此結果會打印1。命令行
假設javascript採用動態做用域,讓咱們分析下執行過程:code
執行foo函數,依然是從foo函數內部查找是否有局部變量value,若是沒有,就從調用函數的做用域,也就是bar函數內部查找value變量,因此結果會打印 2。ip
前面咱們已經說了,javascript採用的是靜態做用域,因此這個例子的結果是1。
也許你會好奇什麼語言是動態做用域?
bash 就是動態做用域,不信的話,把下面的腳本存成例如 scope.bash,而後進入相應的目錄,用命令行執行 bash ./scope.bash,看看打印的值是多少。
value =1 ; function foo(){ echo $value } function bar(){ local value = 2; foo } bar
最後,讓咱們看一個《javascript權威指南》中的例子:
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f() } checkscope()
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f; } checkscope()();
猜猜兩段代碼各自執行結果是多少?
這裏直接告訴你們結果,兩段代碼都會打印: local scope;
緣由也很簡單,由於javascript採用的是詞法做用域,函數的做用域基於函數建立的位置。
而引用《javascript權威指南》的回答是:
javascript 函數的執行用到了做用域鏈,這個做用域鏈是在函數定義的時候建立的。嵌套的函數f()定義在這個做用域鏈裏,其中的變量 scope 必定是局部變量,無論什麼時候何地執行函數 f(),這種綁定在執行f()時依然有效。