這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰markdown
函數定義
的時候就決定了函數調用
的時候才決定的看以下例子:app
let a = 2;
function foo() {
console.log(a); // 會輸出2仍是3?
}
function bar() {
let a = 3;
foo();
}
bar()
複製代碼
假設 JavaScript 採用詞法做用域(也可稱爲靜態做用域),讓咱們分析下執行過程:ide
執行 foo 函數,先從 foo 函數內部查找是否有局部變量 a,若是沒有,就根據書寫的位置,查找上面一層的代碼,也就是 a 等於 2,因此結果會打印 2。函數
假設 JavaScript 採用動態做用域,讓咱們分析下執行過程:post
執行 foo 函數,依然是從 foo 函數內部查找是否有局部變量 a。若是沒有,就從調用函數的做用域,也就是 bar 函數內部查找 a 變量,因此結果會打印 3。ui
前面咱們已經說了,JavaScript 採用的是詞法做用域,因此這個例子的結果是 2。this
詞法做用域是寫代碼的時候就靜態肯定下來的;而動態做用域並不關心函數和做用域是如何聲明以及在何處聲明的,只關心它們從何處調用。換句話說,做用域鏈是基於調用棧的,而不是代碼中的做用域嵌套。lua
Javascript 並不具備動態做用域,它只有詞法做用域,簡單明瞭。可是,它的 eval()、with、this 機制某種程度上很像動態做用域,使用上要特別注意。url
詞法做用域是在寫代碼或者定義時肯定的,而動態做用域是在運行時肯定的(this也是!)。詞法做用域關注函數在何處聲明,而動態做用域關注函數從何處調用。spa
- this 相似動態做用域
- JavaScript 執行是靜態做用域