在JavaScript中,!function(){}()的优点是什么(function(){})()?

And*_*ges 81 javascript design-patterns iife

可能重复:
感叹号在功能之前做了什么?

我长期以来使用以下JavaScript在JavaScript中执行自动执行的匿名函数:

(function () { /* magic happens */ })()
Run Code Online (Sandbox Code Playgroud)

最近,我开始看到以下模式的更多实例(例如,在Bootstrap中):

!function () { /* presumably the same magic happens */ }()
Run Code Online (Sandbox Code Playgroud)

任何人都知道第二种模式的优势是什么?或者,这只是一种风格偏好吗?

Pet*_*son 79

这两种不同的技术具有功能差异以及外观上的差异.一种技术相对于另一种技术的潜在优势将归因于这些差异.

简洁

Javascript是一种简洁非常重要的语言,因为在页面加载时下载 Javascript .这意味着Javascript越简洁,下载时间越快.出于这个原因,有Javascript minifiersobfuscators压缩Javascript文件以优化下载时间.例如,alert ( "Hi" ) ;将优化空间alert("Hi");.

记住这一点,比较这两种模式

  • 正常关闭:   (function(){})() 16个字符
  • 否定关闭:!function(){}() 15个字符

这是一个微观优化,所以除非你正在进行代码高尔夫比赛,否则我认为这不是一个特别引人注目的论点.

否定返回的值

比较的结果值ab.

var a = (function(){})()
var b = !function(){}()
Run Code Online (Sandbox Code Playgroud)

由于该a功能不会返回任何内容,a因此undefined.由于否定undefined就是true,b将评估到true.对于想要否定函数的返回值或者具有一切 - 必须返回非null或未定义值的迷信的人来说,这是一个优势.您可以在其他Stack Overflow问题上看到有关其工作原理的说明.

我希望这有助于您理解这个通常被认为是反模式的函数声明背后的基本原理.

  • 我给了你一个upvote,但我有'简洁'的麻烦... (8认同)
  • 如果意图只是执行函数(这是我如何使用它),那么返回`undefined`实际上对我来说更合适. (5认同)
  • 试图使Javascript源代码简洁只是一个混乱的秘诀.它应该尽可能清楚 - 这个问题的存在使得很明显需要明确JS代码的清晰度!它可以通过您在构建过程中引用的一个minifiers传递. (2认同)

Ski*_*ick 52

对于像这样的问题,我总是依赖Ben Alman的IIFE作品.就我而言,它是决定性的.

这是文章的内容:

// Either of the following two patterns can be used to immediately invoke
// a function expression, utilizing the function's execution context to
// create "privacy."

(function(){ /* code */ }()); // Crockford recommends this one
(function(){ /* code */ })(); // But this one works just as well

// Because the point of the parens or coercing operators is to disambiguate
// between function expressions and function declarations, they can be
// omitted when the parser already expects an expression (but please see the
// "important note" below).

var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

// If you don't care about the return value, or the possibility of making
// your code slightly harder to read, you can save a byte by just prefixing
// the function with a unary operator.

!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// Here's another variation, from @kuvos - I'm not sure of the performance
// implications, if any, of using the `new` keyword, but it works.
// http://twitter.com/kuvos/status/18209252090847232

new function(){ /* code */ }
new function(){ /* code */ }() // Only need parens if passing arguments
Run Code Online (Sandbox Code Playgroud)

  • 呃,javascript是一团糟. (26认同)
  • JS并不是一团糟,它实际上非常强大 - 它只是在点上有一些不太漂亮的语法.;) (7认同)
  • 要记住所有额外的语法(是的,真的,on..do ... false..no,false,off),我认为CoffeeScript的Javascript更复杂.虽然CoffeeScript的字符较少,但并不简单.https://gist.github.com/1248911 (5认同)
  • 它确实节省了1个字节,但我认为它也可能是一个美学的东西.我不认为`!`很漂亮,但我认为它不如嵌套的`((){}())`结构那么难看...... (2认同)

Bri*_*air 14

似乎关键在于你基本上保持解析器不将函数解释为函数声明,而是将其解释为匿名函数表达式.

使用parens对表达式进行分组或使用!否定返回只是改变解析的技巧.然后由以下的parens立即调用它.假设没有明确的回报值,任何和所有这些形式在这方面具有相同的净效应:

(function(){ /* ... */ })(); // Arguably most common form, => undefined
(function(){ /* ... */ }()); // Crockford-approved version, => undefined
!function(){ /* ... */ }();  // Negates the return, so => true
+function(){ /* ... */ }();  // Attempts numeric conversion of undefined, => NaN
~function(){ /* ... */ }();  // Bitwise NOT, => -1
Run Code Online (Sandbox Code Playgroud)

如果您没有捕获返回的值,则没有显着差异.有人可能会说〜可能是一个更快的操作,因为它只是翻转位,或者可能!是一个更快的操作,因为它是一个真/假检查并返回否定.

然而,在一天结束时,大多数人使用这种模式的方式是,他们试图打破一个新的范围,以保持清洁.任何和所有的工作.后一种形式很受欢迎,因为虽然它们确实引入了额外的(通常是不必要的)操作,但是保存每个额外的字

Ben Alman在这个主题上写了一篇精彩的文章:http://benalman.com/news/2010/11/immediately-invoked-function-expression/