注意文中所指做用域和执行上下文都有全局和局部之分,为方便理解采用局部。
本文参考引自: 思否:执行上下文和做用域的理解
做用域:
js中的做用域是词法做用域,即由函数声明时所在的位置决定的。segmentfault
执行上下文:
每次函数调用时,都会产生一个新的执行上下文环境。函数
做用域:
js中的做用域是词法做用域,是在编译阶段就产生的,一整套函数标识符的访问规则。做用域只是一个“空地盘”,其中并无真实的变量,可是却定义了变量如何访问的规则。this
做用域链本质上是一个指向变量对象的指针列表,它只引用不包含实际变量对象。定义了当变量访问不到的时候如何向上查询的一套规则。spa
执行上下文:
每次函数执行都会产生执行上下文,JavaScript引擎会以栈的方式来处理它们,这个栈,咱们称其为函数调用栈(call stack)。栈底永远都是全局上下文,而栈顶就是当前处于活动状态的正在执行的上下文,也称为活动对象(running execution context,图中蓝色的块),区别与底下被挂起的上下文(变量对象)。指针
let fn, bar; // 一、进入全局上下文环境 bar = function(x) { let b = 5; fn(x + b); // 三、进入fn函数上下文环境 }; fn = function(y) { let c = 5; console.log(y + c); //四、fn出栈,bar出栈 }; bar(10); // 二、进入bar函数上下文环境
创建执行上下文阶段(发生在 函数被调用时 && 函数体内的代码执行前 )code
PS:我的以为这个阶段也能够叫编译阶段:首先js是解释型语言,解释一条执行一条。其次函数内部的代码在执行前并无作特殊处理,好比函数体内有语法错误,只有调用了函数才会报错,而在初始化js解析的时候并无发生任何报错信息。
一、 生成变量对象:建立 arguments 对象 --> 建立function函数声明 --> 建立var变量声明;
二、 生成做用域链
三、 肯定this的指向对象
函数执行阶段blog
变量赋值,函数引用,执行其它代码ip
由定义可知,做用域是在函数声明的时候就肯定的一套变量访问规则,而执行上下文是函数执行时才产生的一系列变量的集合体。也就是说做用域定义了执行上下文中的变量的访问规则,执行上下文是在这个做用域规则的前提下执行代码的。作用域