条件语句是否在JavaScript中引入变量的块范围?

时间:2011-03-29 00:16:01

标签: javascript

我对JavaScript代码段有一个小问题,希望您能帮我解决。

var z=0;

function xyz() { 
    if (!z) {
        z+=5;
        var h=15; // The problem resides here
    }
    else { 
        var f=h+7;
        alert(f);
         }
    z++;
    return z;    
}

当我将这个函数注册到按钮元素上的click事件处理程序时,我希望在第二次迭代时看到一个显示警告消息的

22

我所拥有的是 NaN 消息,表明尽管 if 分支中有明确的声明声明,但未定义变量 h 但是当我省略 var 关键字时,突然该函数表现得很好:)

这对我来说真的很令人费解,因为我很确定JS本身不支持块作用域,除非使用Mozilla浏览器引入的 let 关键字。我也很确定使用var关键字声明变量会为它们创建局部范围,因此它们可以在定义它们的函数中独占访问。

那么,为什么在世界上我必须声明 h 作为函数的全局变量?

任何帮助都会非常感激,因为我是Web Design的新手,而且我来自平面设计背景。

注意:实际上,这不是我在编码过程中遇到的现实问题。我试图使用 setInterval()方法自动创建一个每10秒更新一次的自动收报机,然后在用户手动浏览标题时禁止它,当完成后,脚本会再次接管。

我认为更通用和简单的示例更适合解释解决方案,而不会深入了解所使用的方法/属性的细节。

=======

更新

我想我现在明白了。函数没有记忆,因此无法记住先前调用生成的值。我实际上在做的是将第一次调用生成的值存储在一个可以在将来的调用中访问的全局变量中。但我想知道除了使用全局变量之外,还有什么优雅的方法来实现相同的结果吗?

3 个答案:

答案 0 :(得分:6)

没有。实际上,所有局部变量都在函数开头初始化。您的示例代码将按如下方式执行:

function xyz() { 
    var h;
    var f;
    if (!z) {
        z+=5;
        h=15;
    }
    else { 
        f=h+7;
        alert(f);
         }
    z++;
    return z;    
}

您获得NaN因为f=h+7 h已声明,但其值为未定义

还有一种优雅的方式:使用对象。有很多方法可以创建对象,我在这里使用最紧凑的方法:

function MyObject() {
    this.z = 0;
    // it's safer to initialize all your variables (even if you dn't use the initial value)
    this.h = 0;
    this.f = 0;

    this.xyz = function () {
        if (!this.z) {
            this.z += 5;
            this.h = 15;
        } else { 
            this.f = this.h + 7;
            alert(this.f);
        }
        this.z++;
        return this.z;    
    }
}

var o = new MyObject();
o.xyz();
o.xyz();

如果你感兴趣的话,在JS中有很多关于OOP的文档。

答案 1 :(得分:1)

不,只有函数具有局部范围。 将任何内容置于全局范围内,除非您绝对必须这样做。

答案 2 :(得分:0)

您可以使用闭包来获得您想要的结果(例如)。

var xyz = (function() {
  var z = 0;
  var h;

  return function() { 
    var f;

    if (!z) {
      z += 5;
      h = 15;

    } else { 
      f = h + 7;
      alert(f);
    }
    return ++z;
  }
})();

第一次没有显示任何内容,之后始终显示22并且z增加6,7,8等等。

- 罗布