Frage In JavaScript, was ist der Vorteil von! Function () {} () over (function () {}) ()? [Duplikat]


Mögliche Duplikate:
Was bewirkt das Ausrufezeichen vor der Funktion? 

Ich habe lange das Folgende für selbstausführende, anonyme Funktionen in JavaScript verwendet:

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

In letzter Zeit habe ich mehr Instanzen des folgenden Musters gesehen (z. B. in Bootstrap):

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

Weiß jemand, was der Vorteil des zweiten Musters ist? Oder ist es nur eine stilistische Präferenz?


76
2017-09-28 17:02


Ursprung


Antworten:


Diese zwei verschiedenen Techniken haben eine Funktion Unterschied sowie einen Unterschied im Aussehen. Die möglichen Vorteile einer Technik gegenüber der anderen werden auf diese Unterschiede zurückzuführen sein.

Prägnanz

Javascript ist eine Sprache, in der Prägnanz kann sehr wichtig sein, weil Javascript ist heruntergeladen, wenn die Seite geladen wird. Das heißt, je kürzer das Javascript, desto schneller ist die Downloadzeit. Aus diesem Grund gibt es Javascript Minifier und Obfuscatoren Diese komprimieren die Javascript-Dateien, um die Download-Zeit zu optimieren. Zum Beispiel die Leerzeichen in alert ( "Hi" ) ; wäre optimiert auf alert("Hi");.

Denken Sie daran, diese beiden Muster zu vergleichen

  • Normal Schließung: (function(){})()  16 Zeichen
  • Negiert Schließung: !function(){}()  15 Zeichen

Dies ist bestenfalls eine Mikrooptimierung, daher finde ich das nicht besonders überzeugend, es sei denn, Sie machen ein Code Golf Wettbewerb.

Negieren des zurückgegebenen Wertes

Vergleichen Sie den Ergebniswert von a und b.

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

Seit der a Funktion gibt nichts zurück, a wird sein undefined. Seit der Negation von undefined ist true, b wird ausgewertet werden true. Dies ist ein Vorteil für Personen, die entweder den zurückgegebenen Wert der Funktion negieren oder einen Alles-muss-zurückkehren-einen-nicht-null-oder-undefinierten-Wert-Fetisch haben wollen. Sie können eine Erklärung dafür sehen, wie das hier funktioniert andere Stapelüberlauffrage.

Ich hoffe, dass dies Ihnen hilft, die Gründe für diese Funktionsdeklaration zu verstehen, die normalerweise als eine solche angesehen werden Anti-Muster.


78
2017-09-28 17:11



Ich falle immer wieder darauf Ben Almans IIFE Stück Für solche Fragen. Für mich ist es definitiv.

Hier ist das Fleisch von der Artikel:

// 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
2017-09-28 17:19



Es scheint, dass das Entscheidende ist, dass Sie den Parser grundsätzlich davon abhalten, die Funktion als Funktionsdeklaration zu interpretieren, und stattdessen als anonymer Funktionsausdruck interpretiert wird.

Verwenden Sie die Parens, um den Ausdruck zu gruppieren oder verwenden Sie die! Um die Rückkehr zu negieren, sind beides nur Techniken zum Ändern des Parsens. Es wird dann sofort von den folgenden Parens aufgerufen. Alle diese Formen haben in diesem Zusammenhang den gleichen Nettoeffekt, wenn sie keinen expliziten Rückgabewert annehmen:

(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

Wenn Sie den zurückgegebenen Wert nicht erfassen, gibt es keinen signifikanten Unterschied. Man könnte argumentieren, dass das ~ eine schnellere Operation sein könnte, da es nur Bits dreht, oder vielleicht! ist eine schnellere Operation, da es sich um eine echte / falsche Überprüfung handelt und die Negation zurückgegeben wird.

Am Ende des Tages ist die Art und Weise, wie die meisten Leute dieses Muster verwenden, dass sie versuchen, eine neue Ebene des Umfangs abzubrechen, um die Dinge sauber zu halten. Alle arbeiten. Die letzteren Formen sind populär, da sie zwar eine zusätzliche (normalerweise unnötige) Operation einführen, aber das Speichern jedes zusätzlichen Bytes hilft.

Ben Alman hat eine fantastische Zusammenfassung zum Thema: http://benalman.com/news/2010/11/immediately-invoiced-function-expression/


14
2017-09-28 17:21



Das erste "Muster" ruft die anonyme Funktion auf (und hat das Ergebnis ihres Rückgabewerts), während das zweite die anonyme Funktion aufruft und ihr Ergebnis negiert.

Ist es das, was du fragst? Tun sie nicht mach das selbe.


4
2017-09-28 17:07



Es ist fast nur stilistische Vorliebe, abgesehen von der Tatsache, dass ! liefert eine Funktionsrückgabe (d. h. gibt zurück true, die von kommt !undefined).

Außerdem ist es ein Zeichen weniger.


4
2017-09-28 17:10



Nun, im ersten Fall, den Sie verwenden ( ) Um das Objekt, das Sie ausführen möchten, mit dem nächsten Satz zu umbrechen (), und im nächsten Fall verwenden Sie den Operator, der ein Argument (Negationsoperator!) verwendet, und Sie bringen es implizit dazu, sein Argument (funcion) mit zu umbrechen ( ) also bekommst du eigentlich !(function () { })(), führe die Funktion aus und negiere das Ergebnis, das sie zurückgibt. Damit kann auch gearbeitet werden -, +, ~ im gleichen Prinzip, da alle diese Betreiber ein Argument haben.

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

Warum willst du das machen? Ich denke, es ist eine persönliche Vorliebe oder wenn Sie große .JS haben und 1 Char pro anonymer Funktionsaufruf speichern möchten ...: D


1
2017-09-28 17:20