JavaScript运行三部曲
Step1:语法分析
Step2:预编译
Step3:解释执行
今天着重介绍一下预编译的过程,在开始正式介绍预编译之前,还要补充两个小知识:
一个是:暗示全局变量 imply global
这个是说 任何变量,如果未经声明就赋值次变量就归全局所有
a = 123; // 这是一个未经声明就赋值的变量; console.log(a);
我们执行这个代码块的时候,发现不会报错,并且a 可以正常访问~
通过window访问也可以找到a


再来看这样一个函数
function test() { var a = b = 123; } test();

在全局上b是可以找到的,因为b是未经声明就赋值的变量
第二个小知识是: 一切声明的全局变量,全是window的属性
换一种方式理解可以认为 window就是全局的域,我们在定义一个全局变量的时候 ,会存放在window中,当我们需要用到这个变量的时候会到window中寻找
//现在我要定义一个全局变量 var a = 123; //此时,JavaScript为我们开辟了一个空间叫:window /* window{ a :123; } 就像这样一个空间,存放了我们的变量,需要用的时候从这里来拿 */
补充完之后,正式进入预编译的环节,我们经常可以听到一句关于预编译的话:【变量 声明提升, 函数声明 整体提升】,其实这句话只是涵盖了预编译的一部分而已
其实,纵观整个预编译过程(发生在函数执行前一刻),总共要分四个步骤
- 创建AO对象
- 寻找形参和变量声明,把形参和变量声明作为AO对象的属性名,同时赋值为undefined
- 将实参值和形参值相互统一起来
- 在函数体里找函数声明(并非函数表达式)作为属性名(当然已经存在的就不用再次作为属性名啦) ,并把这个函数体整体赋给它。
举个小栗子:
function fn(a){ console.log(a); var a = 123; console.log(a); function a(){} console.log(a); var b = function(){} console.log(b); function d(){} } fn(1); //请问打印结果是啥?
//解题思路 //首先:创建AO对象 Activation Object (执行期上下文) AO{ //第二步:找形参和变量声明 a: undefined; b: undefined; } //第三步: 将实参和形参统一 //此时AO变为如下形式 AO{ a:1; b: undefined; } //第四步:找函数声明 //此时AO变为如下形式 AO{ a: function a() { }; b: undefined; d: function d() { }; } //至此,AO对象创建完毕~~ //现在轮到我们来看每一条的输出是什么
此时万事俱备,开始执行,首先运行到第一条输出
此时我们在AO中查看,此时应该打印 function a(){};
运行到第二条语句:var a = 123;
此时AO发生变化
AO{ a: 123; b: undefined; d: function d() { }; }
运行到第三条语句:
在AO中查看 发现 a:123
所以打印 123;
运行到第四条语句:function a(){} 这条语句在预编译的过程中已经被提升上去了,所以不用管啦!
运行到第五条语句:要求我们打印a
此时AO中的 a 依旧为123;
所以打印 123;
运行到第六条语句:var b = function(){}
此时AO发生变化
AO{ a: 123; b: function() { }; d: function d() { }; }
运行到第七条语句,要求我们打印b
此时AO中 b 为function(){}
所以打印 function(){}
至此,最终答案为:
function a() { }; 123; 123; function() { }
运行结果如下:

小伙伴们,你们做对了吗?
原文链接:https://blog.csdn.net/qq_43377853/article/details/107688617
本文观点不代表 .Net中文网 立场,转载请联系原作者。