var x=0;foo();console.log(x);function foo(){if (true) {x=1;} else {var x=2;}console.log(x);} 运行结果:1,
var x=0; foo(); console.log(x); function foo(){ if (true) { x=1; } else { var x=2; } console.log(x); }
运行结果:1,0原理解析:
JavaScript预编译:
一、先预定义变量,再预定义函数
二、变量的预编译只作声明,不作初始化,初始化在执行时
三、function语句定义的函数,不仅声明了函数名,而且函数体也进行了处理
四、匿名函数不会预编译
预编译结果:
1.foo()函数被预编译,相当于被提到最前面执行,也就是foo()被调用时已经知道这个函数了,虽然foo()函数代码在被调用处的后面。
2.由于变量会预编译,虽然实际运行时else里的var x=2没有运行,但是进行了预编译,foo里的x声明为局部变量。
运行过程解析:
1.调用foo(),console.log()运行时,foo()函数为作用域最前端,在这里查询到局部变量x=1,停止查询,输出1,函数结束后,x这个局部变量被销毁。执行流回到window全局环境。
2.接着运行全局环境的console.log(),在全局环境查到x=0(此处注意,x并不等于1,因为foo的x是局部变量,执行后被销毁),出去0.
3.最终运行结果是:1,0
反例:
var x=0; foo(); console.log(x); function foo(){ if (true) { x=1; } else { x=2; } console.log(x); }
解析:唯一的区别是把else里的var声明去除,使得预编译时foo()里的x变量声明为全局变量,第二次输出时为1,因为全局表里x被赋值为1了,覆盖了前面的x。最终结果是1,1