Kiedy w javascript chcesz użyć tego:
(function(){
//Bunch of code...
})();
Nad tym:
//Bunch of code...
Kiedy w javascript chcesz użyć tego:
(function(){
//Bunch of code...
})();
Nad tym:
//Bunch of code...
Odpowiedzi:
Chodzi o zmienne zakresy. Zmienne zadeklarowane w funkcji samowykonywania są domyślnie dostępne tylko dla kodu w funkcji samowykonywania. Pozwala to na pisanie kodu bez względu na to, jak zmienne są nazywane w innych blokach kodu JavaScript.
Na przykład, jak wspomniano w komentarzu Aleksandra :
(function() {
var foo = 3;
console.log(foo);
})();
console.log(foo);
Spowoduje to najpierw zalogowanie, 3
a następnie zgłoszenie błędu do następnego, console.log
ponieważ foo
nie jest zdefiniowane.
var
, tak: ...function(){ foo=3;}
? Ustawiłoby zmienną globalną, prawda?
function(){ var foo = 3; alert(foo); }; alert(foo);
Więc nadal nie rozumiem
Uproszczony. Tak bardzo normalnie wygląda, jest prawie pocieszające:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
Co jednak jeśli dołączę do mojej strony naprawdę przydatną bibliotekę javascript, która tłumaczy zaawansowane znaki na ich reprezentacje na poziomie podstawowym?
Czekaj, co?
Mam na myśli, czy ktoś wpisuje znak z jakimś akcentem, ale chcę w moim programie tylko „angielskie” znaki AZ? Cóż ... hiszpańskie „ñ” i francuskie „é” można przetłumaczyć na podstawowe znaki „n” i „e”.
Więc ktoś miły napisał obszerny konwerter znaków, który mogę umieścić na mojej stronie ...
Jeden problem: ma w sobie funkcję o nazwie „nazwa” taka sama jak moja funkcja.
To się nazywa kolizja. Mamy dwie funkcje zadeklarowane w tym samym zakresie o tej samej nazwie. Chcemy tego uniknąć.
Więc musimy jakoś zawęzić nasz kod.
Jedynym sposobem na zakodowanie kodu w javascript jest zawinięcie go w funkcję:
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
To może rozwiązać nasz problem. Wszystko jest teraz zamknięte i można uzyskać do niego dostęp tylko z poziomu naszych klamr otwierających i zamykających.
Mamy funkcję w funkcji ... co jest dziwne, ale całkowicie legalne.
Tylko jeden problem. Nasz kod nie działa. Nasza zmienna userName nigdy nie jest wyświetlana w konsoli!
Możemy rozwiązać ten problem, dodając wywołanie do naszej funkcji po naszym istniejącym bloku kodu ...
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
main();
Lub przed!
main();
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Drugi problem: jakie są szanse, że nazwa „główna” nie została jeszcze użyta? ... bardzo, bardzo szczupły.
Potrzebujemy WIĘCEJ zakresu. I jakiś sposób na automatyczne wykonanie naszej funkcji main ().
Teraz dochodzimy do funkcji automatycznego wykonywania (lub samowykonywania, samoczynnego działania, cokolwiek).
((){})();
Składnia jest niezręczna jak grzech. Jednak to działa.
Gdy zawijasz definicję funkcji w nawiasach i dołączasz listę parametrów (inny zestaw lub nawiasy!), Działa ona jak wywołanie funkcji .
Spójrzmy więc jeszcze raz na nasz kod z pewną samowystarczalną składnią:
(function main() {
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
)();
Tak więc w większości samouczków, które czytasz, będziesz bombardowany terminem „anonimowy samowykonanie” lub coś podobnego.
Po wielu latach rozwoju zawodowego zdecydowanie zachęcam do nazwania każdej pisanej funkcji do celów debugowania.
Gdy coś pójdzie nie tak (i tak się stanie), będziesz sprawdzać ślad w przeglądarce. Tak jest zawsze łatwiej zawęzić problemów kodu gdy wpisy w ślad stosu mają imiona!
Niezwykle długa i mam nadzieję, że to pomoże!
:)
Samodzielne wywoływanie (znane również jako automatyczne wywoływanie) ma miejsce, gdy funkcja jest wykonywana natychmiast po jej zdefiniowaniu. Jest to podstawowy wzór i służy jako podstawa wielu innych wzorców programowania JavaScript.
Jestem wielkim fanem :) tego, ponieważ:
Ogromnie - (Dlaczego powinieneś powiedzieć, że to dobrze?)
Więcej tutaj .
Przestrzeń nazw. Zakresy JavaScript są na poziomie funkcji.
Nie mogę uwierzyć, że żadna z odpowiedzi nie wskazuje na globalne implikacje.
(function(){})()
Konstrukcja nie zabezpiecza przed implikowanych globalnych, co jest dla mnie większy niepokój, zobacz http://yuiblog.com/blog/2006/06/01/global-domination/
Zasadniczo blok funkcyjny zapewnia, że wszystkie zdefiniowane przez ciebie „globalne zmienne” są ograniczone do twojego programu, nie chroni cię przed zdefiniowaniem niejawnych globałów. JSHint lub podobny może zawierać zalecenia dotyczące obrony przed takim zachowaniem.
Bardziej zwięzła var App = {}
składnia zapewnia podobny poziom ochrony i może być zawinięta w blok funkcyjny na stronach „publicznych”. (zobacz Ember.js lub SproutCore, aby zapoznać się z przykładami bibliotek używających tej konstrukcji)
Jeśli chodzi o private
właściwości, są one nieco przereklamowane, chyba że tworzysz publiczny framework lub bibliotekę, ale jeśli musisz je zaimplementować, Douglas Crockford ma kilka dobrych pomysłów.
Przeczytałem wszystkie odpowiedzi, brakuje mi czegoś bardzo ważnego , pocałuję się. Są dwa główne powody, dla których potrzebuję samoczynnie wykonujących się funkcji anonimowych, lub lepiej powiedzieć „ Wyrażenie funkcji natychmiast wywołane (IIFE) ”:
Pierwszy został bardzo dobrze wyjaśniony. W przypadku drugiego zapoznaj się z następującym przykładem:
var MyClosureObject = (function (){
var MyName = 'Michael Jackson RIP';
return {
getMyName: function () { return MyName;},
setMyName: function (name) { MyName = name}
}
}());
Uwaga 1: Nie przypisujemy funkcji do MyClosureObject
, co bardziej wynika z wywołania tej funkcji . Pamiętaj o tym ()
w ostatnim wierszu.
Uwaga 2: Co musisz dodatkowo wiedzieć o funkcjach w JavaScript, to że funkcje wewnętrzne mają dostęp do parametrów i zmiennych funkcji, w których są one zdefiniowane.
Wypróbujmy kilka eksperymentów:
Mogę MyName
korzystać getMyName
i działa:
console.log(MyClosureObject.getMyName());
// Michael Jackson RIP
Następujące pomysłowe podejście nie zadziałałoby:
console.log(MyClosureObject.MyName);
// undefined
Ale mogę ustawić inną nazwę i uzyskać oczekiwany wynik:
MyClosureObject.setMyName('George Michael RIP');
console.log(MyClosureObject.getMyName());
// George Michael RIP
Edycja: W powyższym przykładzie MyClosureObject
jest przeznaczony do użycia bez new
prefiksu, dlatego zgodnie z konwencją nie powinien być pisany wielkimi literami.
Czy istnieje parametr, a „Pęczek kodu” zwraca funkcję?
var a = function(x) { return function() { document.write(x); } }(something);
Zamknięcie. Wartość something
zostaje użyta przez funkcję przypisaną do a
. something
może mieć pewną zmienną wartość (dla pętli) i za każdym razem ma nową funkcję.
var x = something;
w funkcji zewnętrznej niż x
parametr: imo jest bardziej czytelny w ten sposób ...
x
i zależy bezpośrednio od zakresu leksykalnego, tj. document.write(something)
...
Może izolacja zakresu. Aby zmienne w deklaracji funkcji nie zanieczyszczały zewnętrznej przestrzeni nazw.
Oczywiście w połowie wdrożeń JS i tak będą.
Oto solidny przykład tego, w jaki sposób przywoływająca się anonimowa funkcja może być przydatna.
for( var i = 0; i < 10; i++ ) {
setTimeout(function(){
console.log(i)
})
}
Wynik: 10, 10, 10, 10, 10...
for( var i = 0; i < 10; i++ ) {
(function(num){
setTimeout(function(){
console.log(num)
})
})(i)
}
Wynik: 0, 1, 2, 3, 4...
let
zamiast var
pierwszym przypadku będzie w porządku.
Ponieważ funkcje w JavaScript są obiektami pierwszej klasy, definiując je w ten sposób, efektywnie definiuje „klasę” podobnie jak C ++ lub C #.
Ta funkcja może definiować zmienne lokalne i zawierać w sobie funkcje. Funkcje wewnętrzne (metody instancji efektywnej) będą miały dostęp do zmiennych lokalnych (efektywnie instancji zmiennych), ale zostaną odizolowane od reszty skryptu.
Funkcja samodzielnego wywołania w javascript:
Wyrażenie samo-wywołujące jest wywoływane (uruchamiane) automatycznie, bez wywoływania. Wywołanie samo-wywołujące jest wywoływane zaraz po jego utworzeniu. Jest to zasadniczo wykorzystywane do unikania konfliktu nazw, a także do uzyskania enkapsulacji. Zmienne lub zadeklarowane obiekty nie są dostępne poza tą funkcją. Aby uniknąć problemów związanych z minimalizacją (filename.min), zawsze używaj własnej funkcji.
Funkcja samodzielnego wykonywania służy do zarządzania zakresem zmiennej.
Zakres zmiennej to region twojego programu, w którym jest zdefiniowany.
Zmienna globalna ma zasięg globalny; jest zdefiniowany wszędzie w kodzie JavaScript i można go uzyskać z dowolnego miejsca w skrypcie, nawet w twoich funkcjach. Z drugiej strony zmienne zadeklarowane w funkcji są zdefiniowane tylko w treści funkcji. Są to zmienne lokalne, mają zasięg lokalny i są dostępne tylko w ramach tej funkcji. Parametry funkcji są również liczone jako zmienne lokalne i są zdefiniowane tylko w treści funkcji.
Jak pokazano poniżej, można uzyskać dostęp do zmiennej globalnej wewnątrz funkcji, a także zauważyć, że w treści funkcji zmienna lokalna ma pierwszeństwo przed zmienną globalną o tej samej nazwie.
var globalvar = "globalvar"; // this var can be accessed anywhere within the script
function scope() {
alert(globalvar);
localvar = "localvar" //can only be accessed within the function scope
}
scope();
Zasadniczo samoczynnie wykonująca się funkcja umożliwia pisanie kodu bez względu na to, jak zmienne są nazywane w innych blokach kodu javascript.
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
W rzeczywistości powyższa funkcja będzie traktowana jako wyrażenie funkcji bez nazwy.
Głównym celem zawinięcia funkcji za pomocą zamkniętego i otwartego nawiasu jest uniknięcie zanieczyszczenia globalnej przestrzeni.
Zmienne i funkcje w wyrażeniu funkcyjnym stały się prywatne (tj.) Nie będą dostępne poza funkcją.
Krótka odpowiedź brzmi: aby zapobiec zanieczyszczeniu o zasięgu globalnym (lub wyższym).
IIFE (Natychmiastowe wywołanie funkcji) jest najlepszą praktyką do pisania skryptów jako wtyczek, dodatków, skryptów użytkownika lub innych skryptów, które powinny współpracować ze skryptami innych osób . Zapewnia to, że każda zdefiniowana zmienna nie wywoła niepożądanych efektów w innych skryptach.
To jest inny sposób na napisanie wyrażenia IIFE. Osobiście wolę tę następującą metodę:
void function() {
console.log('boo!');
// expected output: "boo!"
}();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
Z powyższego przykładu jasno wynika, że IIFE może również wpływać na wydajność i wydajność, ponieważ funkcja, która ma być uruchomiona tylko raz zostanie wykonana raz, a następnie na stałe zrzucona w pustkę . Oznacza to, że deklaracja funkcji lub metody nie pozostaje w pamięci.
void
wcześniej. Lubię to.
Najpierw musisz odwiedzić MDN IIFE , teraz kilka punktów na ten temat
Wygląda na to, że odpowiedź na to pytanie jest już gotowa, ale mimo to opublikuję swoje uwagi.
Wiem, kiedy lubię korzystać z funkcji wykonawczych.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
Ta funkcja pozwala mi użyć dodatkowego kodu do zdefiniowania atrybutów i właściwości childObjects dla czystszego kodu, takich jak ustawianie często używanych zmiennych lub wykonywanie równań matematycznych; O! lub sprawdzanie błędów. w przeciwieństwie do ograniczania się do składni tworzenia instancji obiektów zagnieżdżonych ...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
Kodowanie ma wiele niejasnych sposobów na zrobienie wielu tych samych rzeczy, przez co zastanawiasz się: „Po co zawracać sobie głowę?”. Ale pojawiają się nowe sytuacje, w których nie można już polegać tylko na podstawowych / podstawowych zleceniach.
Biorąc pod uwagę twoje proste pytanie: „W javascript, kiedy chcesz użyć tego: ...”
Lubię @ken_browning i @ sean_holding odpowiedzi, ale oto inny przypadek użycia, o którym nie widzę wspomnianych:
let red_tree = new Node(10);
(async function () {
for (let i = 0; i < 1000; i++) {
await red_tree.insert(i);
}
})();
console.log('----->red_tree.printInOrder():', red_tree.printInOrder());
gdzie Node.insert to asynchroniczna akcja.
Nie mogę po prostu wywołać funkcji oczekiwania bez słowa kluczowego async w deklaracji mojej funkcji i nie potrzebuję nazwanej funkcji do późniejszego użycia, ale muszę czekać na to wywołanie wstawienia lub potrzebuję innych bogatszych funkcji (kto wie?) .
IIRC umożliwia tworzenie prywatnych właściwości i metod.