在JavaScript中,!function(){}()比(function () {})()的优势是什么?[英] In JavaScript, what is the advantage of !function(){}() over (function () {})()?

本文是小编为大家收集整理的关于在JavaScript中,!function(){}()比(function () {})()的优势是什么?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

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

我长期以来一直使用以下内容来自我执行,在JavaScript中的匿名函数:

(function () { /* magic happens */ })()

最近,我已经开始看到更多有关以下模式的实例(例如,在 bootstrap ):

!function () { /* presumably the same magic happens */ }()

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

推荐答案

这两种不同的技术具有功能性差异以及外观差异.一项技术的潜在优势比另一种技术是由于这些差异引起的.

Concision

JavaScript是一种语言, Contision 可能非常重要,因为当页面加载时,JavaScript是下载的.这意味着JavaScript越简洁,下载时间越快.因此,有javascript minifiers and 和 obfuscator 压缩JavaScript文件以优化下载时间.例如,alert ( "Hi" ) ;中的空格将被优化为alert("Hi");.

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

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

这充其量是一个微观的,因此我认为这是一个特别引人注目的论点noreferrer">代码高尔夫竞赛.

否定返回的值

比较a和b的结果值.

var a = (function(){})()
var b = !function(){}()

由于a函数没有返回任何内容,a将为undefined.由于undefined的否定为true,b将评估为true.对于想要否定功能返回价值的人来说,这是一个优势,或者拥有一切持续的返回 - 不可定义的恋物癖.您可以看到有关此方法在此其他堆栈溢出问题.

我希望这可以帮助您理解此功能声明背后的理由,通常将其视为 anti-Pattern .

其他推荐答案

我总是回到 ben alan iife pique 对于这样的问题.就我而言,这是确定的.

这是文章::

// 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

其他推荐答案

似乎关键是您基本上要阻止解析器将函数解释为函数声明,而是将其解释为匿名函数表达式.

使用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

如果您不捕获返回的值,则没有显着差异.有人可能会说〜可能是更快的OP,因为它只是翻转零件,或者也许!是一个更快的OP,因为它是真/错误的检查并返回否定.

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

本·阿尔曼(Ben Alman)关于该主题的文章很棒: http:///benalman.com/news/2010/11/immedise-invoked-function-expression/

本文地址:https://www.itbaoku.cn/post/627654.html

问题描述

Possible Duplicate:
What does the exclamation mark do before the function?

I've long used the following for self-executing, anonymous functions in JavaScript:

(function () { /* magic happens */ })()

Lately, I've started seeing more instances of the following pattern (e.g., in Bootstrap):

!function () { /* presumably the same magic happens */ }()

Anyone know what the advantage is of the second pattern? Or, is it just a stylistic preference?

推荐答案

These two different techniques have a functional difference as well as a difference in appearance. The potential advantages of one technique over the other will be due to these differences.

Concision

Javascript is a language where concision can be very important, because Javascript is downloaded when the page loads. That means that the more concise the Javascript, the faster the download time. For this reason, there are Javascript minifiers and obfuscators that compress the Javascript files to optimize the download time. For example, the spaces in alert ( "Hi" ) ; would be optimized to alert("Hi");.

Keeping this in mind, compare these two patterns

  • Normal closure:   (function(){})() 16 characters
  • Negated closure: !function(){}() 15 characters

This is a micro-optimization at best, so I don't find this a particularly compelling argument unless you are doing a code golf contest.

Negating the returned value

Compare the result value of a and b.

var a = (function(){})()
var b = !function(){}()

Since the a function does not return anything, a will be undefined. Since the negation of undefined is true, b will evaluate to true. This is an advantage to people who either want to negate the returned value of the function or have an everything-must-return-a-non-null-or-undefined-value fetish. You can see an explanation for how this works on this other Stack Overflow question.

I hope that this helps you understand the rationale behind this function declaration that would typically be considered an anti-pattern.

其他推荐答案

I always fall back on Ben Alman's IIFE piece for questions like this. It's the definitive as far as I'm concerned.

Here's the meat of the article:

// 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

其他推荐答案

It seems that the key thing is that you're basically keeping the parser from interpreting the function as a function declaration, and instead it's being interpreted as an anonymous function expression.

Using the parens to group the expression or using the ! to negate the return are both just techniques of changing the parsing. It's then immediately invoked by the following parens. Any and all of these forms are having the same net effect in that regard, assuming no explicit return value:

(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

If you're not capturing the returned value, there's no significant difference. One could argue that the ~ might be a faster op since it's just flipping bits, or maybe ! is a faster op since it's a true/false check and returning the negation.

At the end of the day though, the way most people are using this pattern is that they're trying to break off a new level of scope to keep things clean. Any and all work. The latter forms are popular because while they do introduce an additional (typically unnecessary) operation, saving every extra byte helps.

Ben Alman has a fantastic writeup on the topic: http://benalman.com/news/2010/11/immediately-invoked-function-expression/