原文网址:https://www.youyong.top/article/1159d74dcd6c0

如果你能够都答对可以忽略本文的阅读.免得浪费时间
接下来我要带大家分析下为什么是这样的结果
分析之前你需要明白的是 :创建应用程序的时候,总免不了要声明变量和函数 解析器(interpreter)是如何以及从哪里找到这些数据(变量,函数)的,
当我们引用一个变量时,在解析器内部又发生了什么?
我们知道 变量和执行上下文相关 那么它就应该知道数据储存在哪里以及如何访问这些数据,这种机制被称为变量对象(variable object)。
变量对象(简称为 VO)是与某个执行上下文相关的一个特殊对象,并储存了一下数据
1. 变量(var, VariableDeclaration)
2. 函数声明(FunctionDeclaration, 缩写为FD)
3. 函数形参
也就是所有的执行中的变量都会存储在 这个vo中
- 处理上下文代码的几个阶段 本文最核心的部分了 处理执行上下文代码分为两个阶段:
- 进入执行上下文
- 当进入执行上下文时(在代码执行前),VO 就会被下列属性填充
- 函数的所有形参(如果是在函数执行上下文中)
每个形参都对应变量对象中的一个属性,该属性由形参名和对应的实参值构成,如果没有传递实参,那么该属性值就为 undefined - 所有函数声明(FunctionDeclaration, FD)
每个函数声明都对应变量对象中的一个属性,这个属性由一个函数对象的名称和值构成,如果变量对象中存在相同的属性名,则完全替换该属性。 - 所有变量声明(var, VariableDeclaration)
每个变量声明都对应变量对象中的一个属性,该属性的键/值是变量名和 undefined,如果变量名与已经声明的形参或函数相同,则变量声明不会干扰已经存在的这类属性。

- 执行代码
- 继续以上一例子,到了执行代码阶段,AO/VO 就会修改为如下形式

- 如果你看懂了我上面的分析 接下来我带大家分析几个例子




- 有一点需要说明的是,我们知道,JS中没有块级作用域,只有函数包含的块才会被当做是作用域。诸如for、if等用花括号包含起来的内容是不算作作用域的。
也就是说,其中内容隶属于全局作用域,在全局范围内都可以访问到,如下:

总结
你只要明白了 函数执行分2个阶段 (确定上下文 执行代码) 在确定上下文阶段定义vo(ao)对象值时候 的规则
规则如下
argument(函数的形参) > function声明 > var声明 (也就之前提高的变量提升Hoisting)
- 函数的所有形参(如果是在函数执行上下文中)
每个形参都对应变量对象中的一个属性,该属性由形参名和对应的实参值构成,如果没有传递实参,那么该属性值就为 undefined - 所有函数声明(FunctionDeclaration, FD)
每个函数声明都对应变量对象中的一个属性,这个属性由一个函数对象的名称和值构成,如果变量对象中存在相同的属性名,则完全替换该属性。 - 所有变量声明(var, VariableDeclaration)
每个变量声明都对应变量对象中的一个属性,该属性的键/值是变量名和 undefined,如果变量名与已经声明的形参或函数相同,则变量声明不会干扰已经存在的这类属性。
原文网址:https://www.youyong.top/article/1159d74dcd6c0