JavaScript-Javascript 函数的执行过程问题?

JavaScript-Javascript 函数的执行过程问题?

夜无邪 发布于 2017-09-27 字数 258 浏览 1106 回复 5

这段代码为什么会输出的顺序为什么会是这样,有人能讲解一下原理吗?

a();
function a(){
alert(2);
}
a();
function a(){
alert(1);
}
a();
var a = function() {
alert(3)
}
a();

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

夜无邪 2017-11-09 5 楼

执行过程应该是:1,1,1,3
测试环境:Chrome、FireFox、IE

JS的预编译:对var关键字先提前声明(值先设为undefined,执行时才给实际值),接着对函数定义式进行提前加在var后头,再接着顺序执行代码,函数定义式在预编译时期就被解析,执行时期仍然用这个值,而无论是声明的变量还是声明式函数,在执行的时候,可以覆盖预编译时期的值。

为了方便,从上到下,将四个a(),分别描述成a1,a2,a3,a4
预编译伪代码如下:

var a = undefined;//先将变量a定义成undefined
function a() {//两个函数定义预编译,两个函数同名,因此后面替换前面函数。
alert(1);
}
a1();//第一个调用
a2();//第二个调用
a3();//第三个调用
a = function(){//给变量a赋值
alert(3);
}
a4();//第四个调用

归属感 2017-11-08 4 楼

1, 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。

2, 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined)

答案来源于网络

虐人心 2017-10-27 3 楼

IE下执行顺序为:
1,1,1,3
function 方法应为最后一个被复写的函数被加载,而var作为一个变量则最后被加载.
这个变量之后被调用时,才会被解析

虐人心 2017-10-26 2 楼

测了一下你的代码,发现执行第一步就报错了,不知道你用的浏览器是什么?你所说的执行结果出现了3,2,1,3,是不是你在前面就定义了函数 function a(){alert(3);} ?,看了一下我这边的环境,是因为前面定义了一个a变量,所以报错。

弄了一个纯净的环境,执行结果1,1,1,3 ,这就不难理解了,js预编译后再执行代码

夜无邪 2017-10-26 1 楼

我来说说我对JS解析过程(并未涉及到作用域(链)等其他概念)的理解:
1、js在运行某段代码前,首先要收集该段代码中以关键字“var”声明的变量与以关键字“function”声明的函数;要注意的是,在此阶段,js解释器并不会对变量进行初始化,而只是收集该变量的标识符而已;而对于function,js解释器也对其仅仅进行声明,如果遇到同名的标识符,则按出现的顺序进行覆盖。这也就是大家所说的js预编译或预解析阶段。所以对于问题中的代码,在此阶段,js解释器或者说浏览器得到:

变量a(并没有赋值)
function a(){alert(1)}(前面声明的被覆盖);

2、经过预编译或预解析阶段,js解释器才会自上而下地进行代码的执行。因为我们已经在预编译或预解析阶段已经对函数a进行了声明,所以:

a();  \ alert 1  发生在执行阶段
function a(){   \此段已经被覆盖,即不存在(这发生在预编译阶段),在执行阶段跳过
alert(2);
}
a();  \ alert 1  自上而下继续执行
function a(){  \ 此段在执行阶段跳过
alert(1);
}
a();  \ alert 1  自上而下继续执行
var a = function() {   \对变量a 进行赋值,此时a 是函数字面量,不幸把前面        声明的函数a覆盖(发生在执行阶段)
alert(3)
}
a();    \ alert 3 因为此时的a 已被易主

对于js的运行,各位可以借助于firebug等js调试工具进行查看