当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的区别函数