【问题标题】:Difference between using void vs wrapping in parens for IIFE void function() vs (function())IIFE void function() vs (function()) 使用 void 与在括号中包装之间的区别
【发布时间】:2015-05-03 21:36:23
【问题描述】:

创建模块的常见做法是将它们包装在括号中,这样您就不会在模块之外泄漏任何变量(连接时等)。

还有void 运算符,它计算给定的表达式并返回undefined。 (参见MDN

我想知道为什么更喜欢在括号中包装函数而不是使用void。它是历史性的吗,是否与串联有关?

我知道当其中一个文件缺少分号时,您可能会遇到连接问题,这会导致令人讨厌的问题,直到您注意到它为止。

示例

说,module1.js(注意缺少的逗号):

(function () {
    return function () {
        console.log('module1. I should not be called');
    };
})()

还有,module2.js:

(function () {
    return function () {
        console.log('module2. I should not be called either');
    };
})();

如果你将这些脚本合并成一个包,它会产生这个:

(function () {
    return function () {
        console.log('module1. I should not be called');
    };
})()(function () {
    return function () {
        console.log('module2. I should not be called either');
    };
})();

由于两个模块(文件)都返回一个函数,第二个据称是 IIFE 的调用变成了第一个模块的返回值,有效地调用了console.log。常见的解决方法是使用 !(function (){})(); 声明您的模块,这会强制返回值是布尔值。

但是,如果您要使用 void,例如:

void function () {
    return function () {
        console.log('module1. I should not be called');
    };
}()

拼接后的文件还是会出错,但你会在第一次运行时注意到错误,因此更容易注意到。见下文。

void function () {
    return function () {
        console.log('module1. I should not be called');
    };
}()void function () {
    return function () {
        console.log('module2. I should not be called either');
    };
});

这会抛出Unexpected token void。就模块而言,我相信!(function(){}()void function(){}() 可以达到相同的效果。但我觉得 void 看起来比使用参数包装函数并在其前面加上 ! 更干净(主观)。

我错过了什么?如果我们使用void会不会更好?

【问题讨论】:

  • 解决问题的正确方法是将分号放在它所属的位置,而不是选择不同的模块头。
  • @Bergi 你错过了 OP 的全部要点!他专门尝试使代码对潜在的人为错误更加健壮,而您的解决方案是,“好吧,不要犯任何错误”?!保证没有错误的唯一方法是什么都不做。我们会犯错误,需要找到方法将安全性设计到流程中。
  • @MikeWilliamson:我 linter/stylechecker/etc 也可以发现此类错误,并保证(作为构建过程的一部分)它们不会发生。或者我们可以责怪“捆绑”连接脚本,它的职责实际上是处理这些事情。我相信,正确地进行这种设置比在每个文件中采取大多数不必要的预防措施更好——这可能也是这些事情(void …;(…)!…)从未成功的原因。
  • @MikeWilliamson:另见here。所以“如果我们使用void不是更好吗?”也可以回答为“有更简单的方法可以达到相同的目标”。

标签: javascript iife


【解决方案1】:

嗯,许多 JavaScript 程序员认为 void 令人困惑和多余,尤其是 Douglas Crockford,他称它为 JavaScript 的 "Bad Parts" 之一。

在函数定义之前加上void 可能会特别令人困惑。在像 C++ 这样的语言中,它的意思是“这是一种不返回值的函数”。在 JavaScript 中,void 没有定义任何东西;相反,它计算函数(或其他表达式)并返回值undefined。所以你在 JavaScript 代码中看不到太多。

有关在模块前面使用! 的更多信息,请查看this StackOverflow answer

另外请务必阅读Ben Allman's original blog post on IIFE's

【讨论】:

  • 如您所说,通常最好不要使用void。但我觉得这似乎是证明规则的例外:这里,void实际上不返回值,因为值undefined 立即被丢弃。那么,在这种情况下,使用void 不是更好吗?在我看来,这个案例甚至遵循了 Crockford 最初的问题背后的内在逻辑。除非我遗漏了一些东西......并且有 很多 遗漏,当涉及到奇怪的 Javascript 行为时。
  • 通常 IIFE 无论如何都不会返回值。没必要作废。但是如果你想要它返回一个值,那么这样做:var valueFromIIFE = (function() { return "This value"; })(); 换句话说,你需要包含一个return语句并且将返回的值分配给一个变量。如果是这样的话,那么你不想想把你漂亮的闪亮的新返回值变成未定义的。
猜你喜欢
  • 1970-01-01
  • 2017-12-05
  • 2021-09-29
  • 2015-09-26
  • 2023-02-07
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多