javascript - `var` 中的 `if` 是否会影响 if 是否被评估?

标签 javascript if-statement scope global

这是与 Javascript 作用域和全局与局部变量有关的一些我不太了解的特定微妙之处 - 并且可能导致 if 条件中的代码出现令人惊讶的情况,从而影响是否if 条件被评估:代码受到尚未“发生”的代码的影响。

我已将其缩减为 JSBIN DEMO比较两个几乎相同的代码块。


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

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。

但是,如果我们将 if 中的行更改为使用 var,它会更改变量的状态 达到代码更改之前

在这个变体中,除了在 if 的行中添加 var 之外没有任何变化,变量切换为 undefined 两个之前的行,现在评估 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);

})();

控制台显示变量现在在 if 之前为 undefined,并由现在评估的 if 切换。

编辑:即使 var 语句永远不会发生,同样的事情也会发生:

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);

})();

我认为 JS 代码不可能在代码到达之前影响代码的执行 - 但很明显 var 稍后在代码中的存在以某种方式阻止了整个范围放眼全局。

从jsbin的警告判断,是否认为超出范围取决于范围内是否有var语句,即使那个var语句没有'未被评估或预计不会被评估。

谁能解释一下?


(附带问题,出于好奇,是否还有任何其他 Javascript 执行仅受未评估代码影响的示例?)

最佳答案

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

每当在非全局范围内遇到 var 时,都会在该范围内的 undefined 处声明并初始化一个新变量。由于 if 没有引入新的( block )作用域,if 中的 var 隐藏了父作用域中的 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 .

关于javascript - `var` 中的 `if` 是否会影响 if 是否被评估?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25061219/

相关文章:

Javascript 正则表达式匹配文本中的所有 & 字符,忽略编码,如 ) 等

javascript - 代码中防止网页在iPad上拖动

if-statement - 如果分支覆盖测试中第一个 if 条件为真,else if 条件是否运行?

jquery click 事件的 Javascript 变量范围问题

javascript - 选择 Dropdown coming over bootstrap nav dropdown for hover

Java MVC 和 Rest 服务器以及 JavaScript 重客户端

powershell - -ne 在 Powershell 中不起作用

java 将 null 放入 int 变量中

objective-c - 在@interface 中声明一个ivar 和在@implementation 中放置变量之间的区别

c - C 是否支持作用域解析?