関数の前に感嘆符は何をしますか?


1242
!function () {}();

4
@Dykamその有用性は、この回答で説明されています。stackoverflow.com/questions/5422585/...
hectorct


1
私たちはそれを自己実行匿名関数と呼んでいます ---
befzz

7
@befzzこの記事を後で説明するように、これを即時に呼び出される関数式として参照することをお勧めします(「自己実行」は再帰を意味します)
Zach Esposito

回答:


2118

JavaScript構文101。これは関数宣言です。

function foo() {}

セミコロンがないことに注意してください。これは単なる関数宣言です。foo()関数を実際に実行するには、呼び出しが必要です。

ここで、一見無害な感嘆符を追加!function foo() {}すると、式に変わります。これは関数式になりました

!単体はもちろん、機能呼び出しませんが、私たちは今置くことができます()最後に:!function foo() {}()より高い優先順位を持つ!とすぐに関数を呼び出します。

したがって、作成者が行っているのは、関数式ごとに1バイトを節約することです。それを書くためのより読みやすい方法はこれでしょう:

(function(){})();

最後に!、式をtrueに戻します。これは、デフォルトですべての生命維持のリターンであるundefinedと私たちを残し、!undefinedですtrue。特に役に立たない。


229
+1。これは本当にここでの最良の答えであり、残念ながらほとんど賛成されていません。当然、!ブール値を返しますが、誰もが知っていることですが、関数宣言ステートメントを関数式に変換するので、括弧で囲まずに関数をすぐに呼び出すことができます。明白ではない、そして明らかにコーダーの意図。
gilly3

64
+1これは、実際にこれを実行する理由に対処する唯一の回答であり、返された結果の否定が正当である以上に使用されていることがわかる理由です。単項演算子!(また、〜、-、+)は関数宣言から曖昧さをなくし、末尾の()で括弧が関数をインプレースで呼び出すことを許可します。これは、モジュール式コードを記述するときに、変数のローカルスコープ/名前空間を作成するためによく行われます。
トム・オージェ

65
別の利点はそれです!セミコロンが挿入されるため、このバージョンが;で終わらないファイルと誤って連結されることはありません。()形式がある場合は、前のファイルで定義されたものの関数呼び出しと見なされます。私の同僚への帽子の先端。
Jure Triglav

5
@Carnix var foo =はステートメント/式のあいまいさを解消し、単純にvar foo = function(bar){}("baz");等を書くことができます
Neil

6
これは通常、すべての1バイトがカウントされるminification / uglificationスクリプトによって行われます。
Dima Slivin、2015年

367

関数:

function () {}

何も返しません(または未定義)。

作成した関数をすぐに呼び出したい場合があります。あなたはこれを試してみたくなるかもしれません:

function () {}()

しかし、結果はになりSyntaxErrorます。

!関数の前に演算子を使用すると、式として扱われるため、次のように呼び出すことができます。

!function () {}()

これは、関数の戻り値の反対のブール値(この場合は)も返すtrueため!undefinedですtrue。実際の戻り値を呼び出しの結果にしたい場合は、次のようにしてみてください。

(function () {})()

28
誰がこれを必要とすることができますか?
Andrey

13
これが問題のケースを説明する唯一の答えです、ブラボー!
Andrey

14
2番目のコードサンプルは有効なJavaScriptではありません。の目的は、!関数宣言を関数式に変換することです、それだけです。
Skilldrick 2011

8
@AndreyブートストラップTwitterは、これをすべてのJavaScript(jQuery)プラグインファイルで使用します。他の人も同じ質問をする可能性がある場合に備えて、このコメントを追加します。
Anmol Saraf 2012

2
d3.jsも!function構文を使用します
Kristian

65

!マークされた関数呼び出しに使用するのに良い点がありますairbnb JavaScriptガイドでます

一般に、後で連結される個別のファイル(モジュール)でこの手法を使用するためのアイデア。ここでの注意点は、新しいファイルを新しい行に配置するツールによってファイルが連結されることになっていることです(とにかく、ほとんどの連結ツールの一般的な動作です)。その場合、!以前に連結されたモジュールが末尾のセミコロンを逃した場合にエラーを回避するのに役立ちますが、心配せずにそれらを任意の順序で配置できる柔軟性が得られます。

!function abc(){}();
!function bca(){}();

と同じように機能します

!function abc(){}();
(function bca(){})();

1つの文字を保存し、任意の見栄えが良くなります。

そして、方法のいずれかによって+-~voidあなたは彼らが異なる動作をすることを関数から返すために何かを使用する必要がある場合、オペレータは確かに、機能を呼び出すという点で、同じ効果を持っています。

abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?

しかし、1ファイル1モジュールのコード分離にIIFEパターンを使用し、最適化のために連結ツールを使用する場合(1行1ファイルのジョブになります)、構築

!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()

最初のコードサンプルと同じように、安全なコード実行を行います。

これはエラーをスローし、JavaScript ASIはその作業を実行できなくなります。

!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()

単項演算子に関する1つの注意事項は、それらは同様の作業を行うことになりますが、場合にのみ、最初のモジュールでは使用されませんでした。したがって、連結順序を完全に制御できなければ、安全ではありません。

これは機能します:

!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()

これは:

^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()

3
実際には、これらの他のシンボルは同じ効果を持ちません。はい、説明されているように関数を呼び出すことができますが、同じではありません。考慮してください:var foo =!function(bar){console.debug(bar); }("コウモリ"); どのシンボルを前に置いても、コンソールには「バット」が表示されます。ここで、console.debug( "foo:"、foo);を追加します。-使用するシンボルに基づいて、非常に異なる結果が得られます。!常に望ましいとは限らない戻り値を強制します。わかりやすく正確な({})()構文を使用します。
Carnix 2013年

29

ステートメントがfalseと評価できるかどうかを返します。例えば:

!false      // true
!true       // false
!isValid()  // is not valid

これを2回使用して、値をブール値に強制できます。

!!1    // true
!!0    // false

だから、あなたの質問にもっと直接答えるには:

var myVar = !function(){ return false; }();  // myVar contains true

編集:関数宣言を関数式に変更するという副作用があります。たとえば、次のコードは、必要な識別子(または関数名)がない関数宣言として解釈されるため、無効です。

function () { return false; }();  // syntax error

6
すぐに呼び出される関数で割り当てを使用したい読者のために、わかりやすくするために、サンプルコードでvar myVar = !function(){ return false; }()!同様のものvar myVar = function(){ return false; }()を省略でき、関数は正しく実行され、戻り値は変更されません。
Mark Fox

1
明確に言うと、論理not演算子ので、一度使用してブール値に強制変換できます。!0 = true、!1 = false。JavaScriptの縮小のために、あなたが交換したいと思うtrue!0してfalse!1。2文字または3文字節約できます。
Triynko

9

これは、JavaScriptの縮小化を行うときにデータのバイトを保存するだけです。

以下の無名関数を考えます

function (){}

上記を自己呼び出し関数として作成するには、通常、上記のコードを次のように変更します。

(function (){}())

ここで、関数を呼び出すために必要な、関数の最後に(,)追加すること()を除いて、2つの文字を追加しました。縮小のプロセスでは、通常、ファイルサイズを小さくすることに重点を置きます。したがって、上記の関数を次のように書くこともできます

!function (){}()

それでも、どちらも自己呼び出し関数であり、バイトも保存します。2文字で(,)はなく1文字を使用しました!


1
多くの場合、あなたが縮小さjsの中でこれを参照してくださいよので、これは便利です
名前のために

5

論理否定です演算子です。ブール演算子であり、何かをその逆に反転させます。

関数の前にBANG(!)を使用することにより、呼び出された関数の括弧をバイパスすることができますが、それでも戻り値は反転されます。IEFEの場合と同様に、undefinedが返され、反転するとブール値のtrueになります。

代わりに、必要に応じて閉じ括弧とBANG()を使用してください。

// I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what's happening.

(function(){ return false; }());
=> false

!(function(){ return false; }());
=> true

!!(function(){ return false; }());
=> false

!!!(function(){ return false; }());
=> true

働く他のオペレーター...

+(function(){ return false; }());
=> 0

-(function(){ return false; }());
=> -0

~(function(){ return false; }());
=> -1

結合演算子...

+!(function(){ return false; }());
=> 1

-!(function(){ return false; }());
=> -1

!+(function(){ return false; }());
=> true

!-(function(){ return false; }());
=> true

~!(function(){ return false; }());
=> -2

~!!(function(){ return false; }());
=> -1

+~(function(){ return false; }());
+> -1

5

感嘆符は、すべての関数が常にブール値を返すようにします。
最終値は、関数によって返された値の否定です。

!function bool() { return false; }() // true
!function bool() { return true; }() // false

!上記の例を省略すると、SyntaxErrorになります。

function bool() { return true; }() // SyntaxError

ただし、これを実現するより良い方法は次のとおりです。

(function bool() { return true; })() // true

これは誤りです。!ランタイムが関数を解析する方法を変更します。これにより、ランタイムは関数を(宣言ではなく)関数式として扱います。これにより、開発者は()構文を使用して関数をすぐに呼び出すことができます。!関数式を呼び出した結果にもそれ自体を適用(つまり否定)します。
ベンアストン

3

IIFE(即時に呼び出される関数式)を記述する別の方法。

その別の書き方-

(function( args ) {})()

と同じ

!function ( args ) {}();

まあ、それはまったく同じではありません。2番目の形式は、関数呼び出しの結果を否定します(値の割り当てがないため、それを破棄します)。私はより明示的な(function (args) {...})()構文を厳密に好み、その!function形式は縮小化ツールと難読化ツールに任せます。
トビアス

-1

! 結果としてあなたが期待しているものは何でも否定します(反対です)

var boy = true;
undefined
boy
true
!boy
false

あなたが呼ぶときboy、あなたの結果になりますtrueが、あなたが追加した瞬間は!呼び出すときboy、すなわち!boy、あなたの結果になりますfalse。これはつまり、あなたが意味NotBoyを、それは基本的にはboolean型の結果だ。この時、いずれかtrueまたはfalse

これは!function () {}();式に起こるのと同じことであり、実行function () {}();するとエラーのフラグが立てられるだけです!が、function () {}();式の直前に追加すると、function () {}();が返すはずのの反対になりますtrue。以下に例を示します。

function () {}();
SyntaxError: function statement requires a name
!function () {}();
true
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.