W JavaScript, co jest zaletą!function(){}() over (function () {}) ()? [duplikat]

Możliwy duplikat:
co robi wykrzyknik przed funkcją?

Od dawna używam następujących do samodzielnego wykonywania anonimowych funkcji w JavaScript:

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

Ostatnio zacząłem widzieć więcej instancji następującego wzorca (np. w Bootstrap):

!function () { /* presumably the same magic happens */ }()
Czy ktoś wie jaka jest zaleta drugiego wzoru? Czy to tylko Preferencje stylistyczne?
Author: Community, 2011-09-28

6 answers

Te dwie różne techniki mają funkcjonalną różnicę, a także różnicę w wyglądzie. Potencjalne zalety jednej techniki nad drugą będą wynikać z tych różnic.

Concision

Javascript jest językiem, w którym concision może być bardzo ważne, ponieważ Javascript jest pobierany podczas ładowania strony . Oznacza to, że im bardziej zwięzły Javascript, tym szybszy czas pobierania . Z tego powodu, istnieją minifuzory Javascript i obfuskatory , które kompresują pliki Javascript w celu optymalizacji czasu pobierania. Na przykład spacje w alert ( "Hi" ) ; zostaną zoptymalizowane do alert("Hi");.

Mając to na uwadze, porównaj te dwa wzorce

Jest to mikro-optymalizacja w najlepsze, więc nie uważam tego za szczególnie przekonujący argument, chyba że robisz code golf konkurs.

Negowanie zwracanej wartości

Porównaj wartość wyniku a i b.

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

Ponieważ funkcja a niczego nie zwraca, a będzie undefined. Ponieważ negacja undefined jest true, b oceni do true. Jest to zaleta dla osób, które albo chcą zanegować zwracaną wartość funkcji, albo mają wszystko-musi-zwracać-nie-null-lub-niezdefiniowaną-wartość fetyszu. Możesz zobaczyć wyjaśnienie, jak to działa na tym innym pytaniu o przepełnienie stosu.

Mam nadzieję, że to pomoże Ci zrozumieć uzasadnienie tej deklaracji funkcji, która zazwyczaj byłaby uważana za anty-wzorzec.

 78
Author: Peter Olson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:21

Na takie pytania zawsze wracam do artykułu Bena Almana "życie". To ostateczne, jeśli O mnie chodzi.

Oto mięso Artykuł :

// 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
Author: Skilldrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-28 17:19:27

Wydaje się, że najważniejsze jest to, że w zasadzie powstrzymujesz parser przed interpretacją funkcji jako deklaracji funkcji, a zamiast tego jest ona interpretowana jako anonimowe wyrażenie funkcji.

Używanie parens do grupowania wyrażenia lub użycie ! aby zaprzeczyć zwrotowi, obie są po prostu technikami zmiany parsowania. Jest następnie natychmiast wywoływany przez następujące parens. Każda z tych form ma pod tym względem taki sam efekt netto, zakładając, że nie ma wyraźnego 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

Jeśli nie przechwytujesz zwracanej wartości, nie ma znaczącej różnicy. Można by argumentować, że ~ może być szybszym op, ponieważ to tylko przerzucanie bitów, a może ! jest szybszym op, ponieważ jest to sprawdzanie prawda / fałsz i zwracanie negacji.

Na koniec dnia, większość ludzi używa tego wzoru, ponieważ próbują zerwać nowy poziom zakresu, aby utrzymać porządek. Wszystko działa. Te ostatnie formy są popularne, ponieważ podczas wprowadzają one dodatkową (zazwyczaj niepotrzebną) operację, oszczędzając każdy dodatkowy bajt.

Ben Alman ma fantastyczny tekst na ten temat: http://benalman.com/news/2010/11/immediately-invoked-function-expression/

 14
Author: Brian Arnold Sinclair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-28 17:21:14

Pierwszy "wzorzec" wywołuje funkcję anonimową (i ma wynik jej zwracanej wartości), podczas gdy drugi wywołuje funkcję anonimową i neguje jej wynik.

O to pytasz? Oni robią NIE robią to samo.

 4
Author: Blindy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-28 17:07:14

Jest to prawie tylko preferencja stylistyczna, z wyjątkiem faktu, że ! zapewnia zwracanie funkcji (tzn. zwraca true, które pochodzi z !undefined).

Poza tym, jest o jedną postać mniej.
 4
Author: doctorless,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-18 12:18:51

Dobrze w pierwszym przypadku używasz ( ) aby zawinąć obiekt, który chcesz wykonać z następnym zestawem (), a w następnym przypadku używasz operatora, który przyjmuje jeden argument (operator negacji !) i sprawiasz, że domyślnie owija ona swój argument (funcion) ( ), więc w rzeczywistości otrzymujesz !(function () { })(), wykonujesz funkcję i negujesz wynik, który zwraca. Może to również działać z -, +, ~ na tej samej zasadzie, ponieważ wszystkie te operatory przyjmują jeden argument.

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

Dlaczego chcesz zrobić to? Myślę, że jest to osobiste preferencje lub jeśli masz duże .JS i chcesz zapisać 1 znak na anonimowe wywołanie funkcji... : D

 1
Author: Cipi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-28 17:20:58