使用void作为语法糖来防止隐式全局变量,是或否?

时间:2011-03-12 18:32:49

标签: javascript syntax syntactic-sugar

我一直在考虑javascript编程风格,我想知道是否有必要添加一些语法糖以防止使用隐式全局的容易犯的错误,即:

var OuterFunction = function() { // closure container
    var renamedCounter = 0; // someone renamed counter,
    this.resetCounter = function () {
        counter = 0; // ... but forgot to check the inner functions as well.
        return this;
    };
    return this;
}

在这个例子中,计数器突然变成一个全局变量,而不是一个变量 本地作用于OuterFunction的实例。

通过'声明'一个闭包捕获的变量void,你得到一个免费的断言 与使用counter但没有分配的任何其他代码一样。

this.resetCounter = function () {
    void counter; // this will throw an Error if counter is not in scope.
    counter = 0;
    return this;
};

编辑:正如 jleedev 所指出的,只是使用变量名称本身似乎在测试是否 它存在,即

this.resetCounter = function () {
    counter;
    counter = 0;
    return this;
};

也会起作用。

我看到的优点是:

  • 这是写作的简短。
  • 看起来就像一个变量声明,它在某种程度上。
  • 编辑添加:如果一致地完成,则语法检查程序(肉类或程序)很容易发现此类错误。

另一方面:

  • 令人困惑。代码实际上并没有任何事情。
  • 未来的口译人员可能会将其视为毫无意义,无副作用的代码,并对其进行优化。

我有什么方面可以忽略吗?这是一个愚蠢的想法,还是至少有点可辩护?

提问者的编辑:这应该是社区维基问题,但我没有看到一个复选框将其更改为该问题。我含糊地回忆起有一个。

为愚蠢而编辑:当然,+=会在递增之前尝试检索表达式的值。因此,将示例重命名为resetCounter而不是incrementCounter,以便更有意义。

2 个答案:

答案 0 :(得分:3)

根据ECMASCript Language specification

  

11.4.2 void运算符

     

制作UnaryExpression:void   UnaryExpression评估为   如下:

     
      
  1. 让expr成为评估UnaryExpression的结果。
  2.   
  3. 调用GetValue(expr)。
  4.   
  5. 返回undefined。
  6.         

    注意必须调用GetValue,即使它的值未被使用,因为它可能有可观察到的副作用。

所以它永远不应该被优化掉。

然而,IMHO看起来并不像“声明”一个变量,当然也不像一个变量,所以应该避免。

编辑:确实不应该使用它,因为GetValue调用可能有副作用,例如,如果变量实际上是一个带有“getter”的属性。

答案 1 :(得分:1)

不确定这是否是您问题的答案,但ECMAScript 5 introduces the strict mode会阻止隐式全局声明:

  

分配给未声明的标识符或以其他方式无法解析的引用不会在全局对象中创建属性。在严格模式代码中进行简单赋值时,其 LeftHandSide 不得求值为不可解析的引用。如果是,则抛出 ReferenceError 异常(8.7.2)。 LeftHandSide也可能不是对具有属性值{[[Writable]]: false }的数据属性的引用,而是对属性值为{[[Set]]: undefined },也不是[[Extensible]]内部属性值 false 的对象的不存在属性。在这些情况下,会抛出 TypeError 异常(11.13.1)。

在支持它的浏览器中(目前似乎只是Firefox 4),您可以使用

激活严格模式
"use strict";

在开发过程中,我使用JSLint检查我的文件是否有错误或有问题的代码。它使你不了解隐含的全局变量。