JavaScriptでは、(function(){})()よりも!function(){}()の利点は何ですか?

design-patterns iife javascript
JavaScriptでは、(function(){})()よりも!function(){}()の利点は何ですか?

_
可能な重複: + https://stackoverflow.com/questions/3755606/what-does-the-exclamation-mark-do-before-the-function [関数の前に感嘆符は何をしますか?]
_

JavaScriptの自己実行型の匿名関数には、長い間以下を使用していました。

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

最近、次のパターンのインスタンスが増え始めています(例:https://github.com/twitter/bootstrap/blob/master/js/bootstrap-alerts.js[Bootstrap]):

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

誰もが2番目のパターンの利点を知っていますか? または、それは単なる文体的な好みですか?

  79  31


ベストアンサー

これらの2つの異なる手法には、機能的なhttp://en.wikipedia.org/wiki/Bohemian_culture[difference]と外観の違いがあります。 1つの手法が他の手法よりも優れている可能性は、これらの違いによるものです。

簡潔さ

Javascriptは、ページがロードされるときにダウンロードされるため、* concision *が非常に重要になる可能性がある言語です。 つまり、Javascriptが簡潔であればあるほど、ダウンロード時間は短くなります。 このため、ダウンロード時間を最適化するためにJavascriptファイルを圧縮するJavascript minifiersおよびhttp://javascript-obfuscator.com/[obfuscators]があります。 たとえば、 `alert(” Hi “);`のスペースは `alert(” Hi “);`に最適化されます。

これを念頭に置いて、これら2つのパターンを比較してください

  • 正常
    closure
    (function(){})() 16文字

  • * http://en.wikipedia.org/wiki/Negation [Negated]閉鎖*:
    !function(){}() 15文字

これはせいぜいマイクロ最適化であるため、http://en.wikipedia.org/wiki/Code_golf [code golf]コンテストを行っていない限り、これは特に説得力のある議論ではありません。

戻り値を否定する

「a」と「b」の結果値を比較します。

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

「a」関数は何も返さないため、「a」は「undefined」になります。 「undefined」の否定は「true」なので、「b」は「true」と評価されます。 これは、関数の戻り値を無効にしたい、またはすべてを返す必要があり、nullまたはundefined-valueのフェチが必要な人にとっては利点です。 このhttps://stackoverflow.com/questions/3755606/what-does-the-exclamation-mark-do-before-the-function/3755656#3755656 [その他のスタックオーバーフローの質問]でこれがどのように機能するかの説明を見ることができます。 ]

これが、通常https://meta.stackexchange.com/questions/41976/question-title-that-doesnt-describe-the-problem/42064#42064と見なされるこの関数宣言の背後にある理論的根拠を理解するのに役立つことを願っています[アンチパターン]。

79


このような質問については、常にhttp://benalman.com/news/2010/11/immediately-invoked-function-expression/[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

51


重要なことは、基本的にパーサーが関数を関数宣言として解釈しないようにし、代わりに匿名関数式として解釈されることです。

括弧を使用して式をグループ化するか、! 戻り値を無効にすることは、どちらも解析を変更するための単なるテクニックです。 その後、次の括弧によってすぐに呼び出されます。 明示的な戻り値がないと仮定すると、これらの形式のすべてがその点で同じ正味の効果を持っています:

(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

返された値をキャプチャしていない場合、大きな違いはありません。 〜のほうがビットを反転するだけなので、より高速な操作になる可能性があると主張することもできます。 これは、true / falseチェックであり、否定を返すため、より高速なopです。

しかし、結局のところ、ほとんどの人がこのパターンを使用する方法は、物事をきれいに保つために新しいレベルのスコープを打ち破ろうとしているということです。 すべての仕事。 後者の形式は、追加の(通常は不要な)操作を導入しますが、余分なバイトをすべて保存すると役立つため、一般的です。

ベン・アルマンのトピックに関する素晴らしい記事があります:http://benalman.com/news/2010/11/immediately-invoked-function-expression/

14


最初の「パターン」は匿名関数を呼び出し(その戻り値の結果を取得します)、2番目は匿名関数を呼び出してその結果を否定します。

あなたが求めているのはそれですか? 彼らは同じことを_しません_。

4


!`が関数の戻り値を提供するという事実(つまり、 `!undefined`に由来する true`を返します)。

また、文字が1つ少なくなります。

4


最初のケースでは、実行したいオブジェクトを次のセットの(() でラップするために() `を使用しています。次のケースでは、1つの引数を取る演算子(否定演算子!)を使用しています。引数(関数)を暗黙的に `()`でラップしているので、実際に `!(function(){})()`を取得し、関数を実行して、返される結果を否定します。 これらの演算子はすべて1つの引数を取るため、これは同じ原理で `-、+、〜`でも機能します。

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

なぜあなたはこれをしたいのですか? 個人的な好みか、大きな.JSがあり、匿名関数呼び出しごとに1文字を節約したい場合は…​
😀

1


タイトルとURLをコピーしました