Niedawno porównałem bieżącą wersję json2.js z wersją, którą miałem w swoim projekcie i zauważyłem różnicę w sposobie tworzenia i wykonywania wyrażenia funkcji.
Kod używany do zawijania anonimowej funkcji w nawiasach, a następnie wykonywania jej,
(function () {
// code here
})();
ale teraz zawija funkcję wykonywaną automatycznie w nawiasach.
(function () {
// code here
}());
CMS zawiera komentarz w zaakceptowanej odpowiedzi składni zamkniętej funkcji anonimowej Explain JavaScript, że „oba: (function(){})();
i (function(){}());
są prawidłowe”.
Zastanawiałem się, jaka jest różnica? Czy te pierwsze zajmują pamięć, pozostawiając globalną, anonimową funkcję? Gdzie powinien znajdować się nawias?
javascript
syntax
anonymous-function
iife
Kevin Hakanson
źródło
źródło
Odpowiedzi:
Są praktycznie takie same.
Pierwszy zawija funkcję w nawiasach, aby uczynić ją prawidłowym wyrażeniem i wywołuje ją. Wynik wyrażenia jest niezdefiniowany.
Drugi wykonuje funkcję, a nawiasy wokół automatycznego wywołania sprawiają, że jest to prawidłowe wyrażenie. Ocenia również jako niezdefiniowany.
Nie sądzę, aby można było to zrobić „we właściwy” sposób, ponieważ wynik wyrażenia jest taki sam.
źródło
+function(){}()
lub!function(){}()
.-function(){}();
,!function(){}();
, iw zasadzie każdy inny operator tuż przedfunction
też praca, ale bym trzymać się wersji z użyciem nawiasów). Pierwszą widzę znacznie częściej niż drugą i to moje preferencje; dla mnie też ma to większy sens, ale to subiektywne. FWIW: jsbin.com/ejaqowW takim razie to nie ma znaczenia. Wywołujesz wyrażenie, które jest rozpoznawane jako funkcja z pierwszej definicji oraz definiujesz i natychmiast wywołujesz funkcję w drugim przykładzie. Są podobne, ponieważ wyrażenie funkcji w pierwszym przykładzie jest po prostu definicją funkcji.
Istnieją inne, bardziej użyteczne przypadki wywoływania wyrażeń, które dają funkcje:
źródło
foo = function(){alert('hi');}
. jeśli żadna z nich nie jest funkcją, generowany jest błąd.foo
jest „prawda”, ale nie jest funkcją.Nie ma żadnej różnicy poza składnią.
Jeśli chodzi o twoje obawy dotyczące drugiej metody zrobienia tego:
Rozważać:
(function namedfunc () { ... }())
namedfunc
nadal nie będzie w zasięgu globalnym, mimo że podałeś nazwę. To samo dotyczy funkcji anonimowych. Jedynym sposobem uzyskania go w tym zakresie byłoby przypisanie go do zmiennej wewnątrz parens.Zewnętrzne parens są niepotrzebne:
Ale i tak nie chciałeś tej globalnej deklaracji, prawda?
A więc sprowadza się to do:
I możesz to jeszcze bardziej zredukować: nazwa jest niepotrzebna, ponieważ nigdy nie będzie używana (chyba że twoja funkcja jest rekurencyjna ... a nawet wtedy możesz użyć
arguments.callee
)Tak o tym myślę (może się nie zgadza, nie czytałem jeszcze specyfikacji ECMAScript). Mam nadzieję, że to pomoże.
źródło
arguments.callee
jest to przestarzałe od wersji ES5 (i zabronione w trybie ścisłym).Różnica istnieje tylko dlatego, że Douglasowi Crockfordowi nie podoba się pierwszy styl IIFE ! (poważnie) Jak widać na tym filmie !! .
Jedynym powodem istnienia dodatkowego zawijania
()
{w obu stylach} jest pomoc w utworzeniu tej sekcji kodu Wyrażenie funkcji , ponieważ nie można natychmiast wywołać deklaracji funkcji . Niektóre skrypty / Minify-ers tylko stosowanie+
,!
,-
i~
zamiast zbyt nawiasach. Lubię to:A wszystko to jest dokładnie takie samo, jak twoje alternatywy. Wybór spośród tych przypadków jest całkowicie samodzielny i nie ma znaczenia. {Te, które
()
produkują plik większy o 1 bajt ;-)}źródło