在`if`中存在`var`会影响if是否被评估?

时间:2014-07-31 14:16:03

标签: javascript if-statement scope global

这是与Javascript作用域和全局与局部变量有关的一些特殊细微之处,我不太了解 - 并且可能导致if条件内的代码令人惊讶的情况影响到{评估{1}}条件:代码受到没有发生的代码的影响'爱好。

我已经将它缩小到这个JSBIN DEMO,比较两个几乎相同的代码块。


首先,一切都按预期发生。我们定义一个全局变量,然后在一个范围内,我们检查它是否被定义,看到它是什么,并继续:

if

控制台显示变量是一个函数,并且跳过if,如预期的那样。

,如果我们将someVar = function(){}; // or, window.someVar =... (function(){ console.log("before", someVar, typeof someVar); if(typeof someVar == 'undefined'){ someVar = true; } console.log("after", someVar, typeof someVar); })(); 中的行更改为使用if,则会更改变量之前的状态达到了代码中的更改

在此变体中,除varvar内的行中添加if之外没有任何变化,变量先前切换为undefined两行,{{1}现在评估:

if

控制台在someVar = function(){}; // or, window.someVar =... (function(){ console.log("before", someVar, typeof someVar); if(typeof someVar == 'undefined'){ var someVar = true; // <<<<< the only change is adding var here } console.log("after", someVar, typeof someVar); })(); 之前显示变量undefined,并由现在评估的if切换。

修改:即使if语句永远不会发生,也会发生同样的事情:

var

我没有想到JS代码可能会在代码到达之前影响代码的执行 - 但显然代码中neverVar = function(){}; // or, window.neverVar ... (function(){ console.log("never-before", neverVar, typeof neverVar); if(false){ // never do this var neverVar = "changed"; } console.log("never-after", neverVar, typeof neverVar); })(); 的存在显然会以某种方式停止从全球范围看整个范围。

根据jsbin的警告判断,是否将其视为超出范围取决于范围内是否有var声明,即使var声明没有&#39}。已被评估或预计不会被评估。

有人可以解释一下吗?


(旁边的问题,出于好奇,还有其他任何Javascript执行的例子都受到未评估代码存在的影响吗?)

1 个答案:

答案 0 :(得分:2)

它被称为variable hoisting,其中变量和函数声明在实际执行其余代码之前被处理。

每当在非全局范围内遇到var时,就会在该范围内的undefined声明并初始化一个新变量。由于if未引入新的(块)范围,var内的if会影响父范围内的var


奖励:关于你的问题是否有任何其他JavaScript执行的例子受到无法访问的代码的影响:是的,但仅限于性能方面。现代JavaScript解释器非常复杂,并尽可能地优化解释代码。有some constructs会导致性能下降,即使它位于无法访问的代码块中。例如:

for (var i=0; i<100000000; ++i) ; // Busy loop
if (false) {
   eval(); // BOOM - Killed optimizations.
}

查看基准测试:包含eval的代码段的运行速度明显慢于没有http://jsperf.com/eval-hurts-performance的代码段。