當javascript代碼執行從一個函數進入到另外一個函數的時候,語言在實現上爲當前執行函數保存外部的執行環境(變量),在當前函數進行變量標識符查找的時候,查找的規則是首先在當前的執行環境中查找對應的變量,而後逐步從上級的執行環境中查找.這種對變量實現的存儲和查找機制就是javascript中的做用鏈域.下面先從一些js執行環境的基礎知識提及,而後從ECMA的規範上理解javascript的執行環境.javascript
執行棧是存儲javascript執行上下文的一種結構,它具備先入先出的特色.javascript在執行的時候會建立全局的執行上下文.在執行到函數代碼的時候,會建立新的執行上下文,執行完對應函數的時候,會退出當前的上下文回到以前的執行上下文繼續代碼的執行.html
javascript在建立執行上下文的時候,會對當前執行環境聲明的變量進行綁定(初始化存儲位置),這個在必定程度上也解決了函數聲明的前後順序問題,下面這段代碼是能夠正常執行的java
console.log(a);// undefined
var a = 0;// let const與var的區別是在建立對應的以後環境的時候是let const不會爲變量綁定初始值,
var會綁定初始值(undefined),引用一個沒有初始值的變量會報錯
test();
function test() { test2(); }
function test2() { console.log(1); }複製代碼
在javascript進入到函數的執行代碼的時候,會建立新的執行上下文,將當前的上下文推入執行棧進行代碼的執行.下面先簡單的理解執行上下文的基本組件:bash
Execution Contexts = {
code evaluation state // 代碼執行的狀態 用戶代碼的執行暫停和恢復
Realm // realm是對javascript執行邊界的一些限制
LexicalEnvironment:{
this // 會進行this的bind 理解this是當前函數的caller
Environment Record // 用於初始化和存儲當前上下文聲明的函數聲明,變量
outer LexicalEnvironment // 用於從外部的做用域查找標識符(做用域鏈) }
VariableEnvironment: {} // VariableEnvironment和LexicalEnvironment
是類似的概念下面會單獨進行講解
}複製代碼
this是指調用函數的caller.在進入函數執行的時候會建立新的執行上下文而且對this進行綁定(箭頭函數使用的是Lexical this,即這個函數被建立時的this就是函數內部的this).閉包
const obj = {
name: 100,
test: function() { console.log(this.name); }
};
obj.test(); // 100
const obj2 = {
name: 200,
test: () => {
console.log(this.name); // 這段代碼的執行環境是全局的環境
因此箭頭函數中this的指向是window
}
}
obj2.test(); // undefined 複製代碼
上面的代碼塊中obj是一個引用類型,在ECMA規範中有引用類型的定義,能夠理解成下面的形式app
Reference {
the base value component // 引用類型的值 對於上面的例子來講就是obj自己
the referenced name component // 引用類型的名字
// the Boolean-valued strict reference flag
} 複製代碼
在執行上下文中確認this的指向可使用以下的規則: ecmascript
function test() { var a = 10 var obj = {a:20} with(obj) { var test2 = function() { console.log(a) } function test3() { console.log(a) } } return {test2,test3} } var hah = test() hah.test2() //log 20 hah.test3()//log 20 複製代碼
當前的函數存在對外部做用域變量的訪問會造成閉包.閉包保存的是生成閉包時候的執行上下文的LexicalEnvironment. (Closure is when a function remembers and accesses variables from outside of its own scope, even when that function is executed in a different scope.)ide
VariableEnvironment和LexicalEnvironment的區別函數