JavaScript深刻之詞法做用域和動態做用域

做用域

做用域是指程序源代碼中定義變量的區域。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()時依然有效。

參考文章:https://github.com/mqyqingfeng/Blog/issues/2

相關文章
相關標籤/搜索