06 JS执行顺序:编译+执行
1、编译阶段
编译阶段会生成两部分内容:
- 创建执行上下文 The Creation Phase
- 可执行代码
创建执行上下文(Execution context)
定义:执行上下文是JavaScript执行一段代码时的运行环境。比如调用一个函数,就会进入这个函数的执行上下文,确定该函数在执行期间用到的诸如this、变量、对象以及函数等。
对于每个执行上下文,都有三个重要属性:
-
1、this
-
2、建立 作用域链 (Scope chain) - 词法环境:当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样 由多个执行上下文的变量对象构成的链表 就叫做作用域链
-
3、生成 变量对象 (Variable object,VO) - 该对象中保存了变量提升的内容
详解如下:
-
1、this 值的决定,即我们所熟知的 This 绑定
-
全局执行上下文中:
this
指向全局对象(浏览器中 -window
) -
函数执行上下文中:
this
的值取决于该函数是如何被调用的。- 如果它被一个 引用对象 调用,那么
this
会被设置成那个对象,否则this
的值被设置为全局对象或者undefined
(在严格模式下)。
foo.baz(); // 'this' 引用 'foo', 因为 'baz' 被对象 'foo' 调用 let bar = foo.baz; bar(); // 'this' 指向全局 window 对象,因为没有指定引用对象
- 如果它被一个 引用对象 调用,那么
-
-
2、作用域链 - 创建词法环境组件 —
let/const
-
定义:词法环境由 环境记录器(存储变量和函数声明的实际位置 – 作用域在函数定义的时候就决定) 和一个 外部词法环境的引用(可以访问其父级词法环境 - 作用域链) 组成。
-
词法环境有两种类型:
- 全局环境 没有外部环境引用的词法环境 ->
null
;环境记录器用于定义全局上下文中的变量和函数 - 函数环境 外部环境引用可能是全局环境,也可能是任何包含此内部函数的外部函数;环境记录起用于存储变量、函数、参数
- 全局环境 没有外部环境引用的词法环境 ->
-
-
3、创建 变量环境 组件 —
var
-
定义:同样是一个词法环境,其环境记录器持有 变量声明语句 在执行上下文中创建的绑定关系
-
过程:
①首先 建立arguments对象(函数参数) :检查当前上下文中的参数,建立该对象下的属性与 属性值②其次会处理函数声明 :在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用③再会 处理变量声明,变量对象中以变量名建立一个属性,属性值为
undefined
,**如果变量与函数同名,则 在这个阶段,以函数值为准**,如下例子:
-
2、执行阶段
按照顺序一行一行地执行可执行代码
注意:
- 一段代码如果定义了两个相同名字的函数,那么最终生效的是最后一个函数
function showName() { console.log('我是个坑'); } showName(); function showName() { console.log('我还是个坑'); } showName(); // 我还是个坑
输出的结果是:‘我还是个坑’