Natychmiast wywołane wyrażenie funkcji

wyrażenie funkcyjne (lub IIFE , wymawiane "iffy", IPA /ˈɪf.i/) to idiom języka programowania , który tworzy zakres leksykalny przy użyciu zakresu funkcji . Był popularny w JavaScript jako metoda wspomagająca programowanie modułowe przed wprowadzeniem bardziej standaryzowanych rozwiązań, takich jak moduły CommonJS i ES .

Natychmiastowo wywoływane wyrażenia funkcyjne mogą służyć do unikania podnoszenia zmiennych z bloków, ochrony przed zanieczyszczeniem środowiska globalnego i jednocześnie umożliwiania publicznego dostępu do metod przy zachowaniu prywatności zmiennych zdefiniowanych w ramach funkcji.

Stosowanie

Natychmiastowo wywoływane wyrażenia funkcyjne mogą być zapisywane na wiele różnych sposobów. Powszechną konwencją jest umieszczanie wyrażenia funkcji – i opcjonalnie jego operatora wywołania – w nawiasach operatorem grupowania, aby jawnie powiedzieć parserowi, aby oczekiwał wyrażenia. W przeciwnym razie w większości sytuacji, gdy parser napotka słowo function , potraktuje je jako deklarację (instrukcję) funkcji, a nie jako wyrażenie funkcyjne.

    
    
      (  funkcja  ()  {  /* ... */  })();  (  funkcja  ()  {  /* ... */  } ());  (()  =>  {  /* ... */  })();  // Z funkcjami strzałek ES6 (chociaż nawiasy są dozwolone tylko na zewnątrz) 

Istnieją inne sposoby wymuszenia wyrażenia funkcji: [ potrzebne źródło ]

    
    
    
    
     
     
      !  funkcja  ()  {  /* ... */  }();  ~  funkcja  ()  {  /* ... */  }();  -  funkcja  ()  {  /* ... */  }();  +  funkcja  ()  {  /* ... */  }();  pusta  funkcja  ()  {  /* ... */  }();  usuń  funkcję  ()  {  /* ... */  }();  typ  funkcji  ()  {  /* ... */  }(); 
      funkcja  oczekiwania  ()  {  /* ... */  }(); 

W kontekstach, w których oczekiwane jest wyrażenie, zawijanie w nawiasy nie jest konieczne:

       
      
0      niech  f  =  funkcja  ()  {  /* ... */  }();  prawda  &&  funkcja  ()  {  /* ... */  }();  ,  funkcja  ()  {  /* ... */  } (); 

Przekazywanie zmiennych do zakresu odbywa się w następujący sposób:

      (  funkcja  (  a  ,  b  )  {  /* ... */  })(  "witaj"  ,  "świecie"  ); 

Nawias początkowy to jeden przypadek, w którym automatyczne wstawianie średnika (ASI) w JavaScript może powodować problemy; zamiast tego wyrażenie jest interpretowane jako wywołanie ostatniego terminu w poprzednim wierszu. W niektórych stylach, które pomijają opcjonalne średniki, średnik jest umieszczany przed nawiasem okrągłym i jest znany jako średnik obronny . Na przykład:

    
  
  
 a  =  b  +  c  ;(  funkcja  ()  {  // kod  }) (); 

... aby uniknąć parsowania jako c() .

Przykłady

Kluczem do zrozumienia wzorców projektowych, takich jak IIFE, jest uświadomienie sobie, że przed ES6 JavaScript zawierał tylko zakres funkcji (a więc nie miał zakresu blokowego ), przekazując wartości przez referencję wewnątrz domknięć . Już tak nie jest, ponieważ JavaScript w wersji ES6 implementuje określanie zakresu bloków przy użyciu nowych let i const .

Kontekst oceny

Brak zakresu blokowego oznacza, że ​​zmienne zdefiniowane wewnątrz (na przykład) pętli for będą miały swoją definicję „podciągniętą” na górę otaczającej funkcji. Ocena funkcji zależnej od zmiennych zmodyfikowanych przez funkcję zewnętrzną (w tym przez iterację) może być trudna. Możemy to zobaczyć bez pętli, jeśli zaktualizujemy wartość między zdefiniowaniem a wywołaniem funkcji.

  
  
       
  

  niech  v  ,  pobierz wartość  ;  v  =  1  ;  getValue  =  function  ()  {  return  v  ;  };  v  =  2  ;  pobierzWartość  ();  // 2 

Podczas gdy wynik może wydawać się oczywisty podczas ręcznej aktualizacji v , może to spowodować niezamierzone wyniki, gdy getValue() jest zdefiniowana wewnątrz pętli.

Odtąd funkcja przekazuje v jako argument i jest natychmiast wywoływana, zachowując kontekst wykonania funkcji wewnętrznej.

  
  
    
          

  

   niech  v  ,  pobierz wartość  ;  v  =  1  ;  getValue  =  (  funkcja  (  x  )  {  return  funkcja  ()  {  return  x  ;  };  })(  v  );  v  =  2  ;  pobierz wartość  ;  // 1 

Jest to równoważne z następującym kodem:

  
  
  
          

  
  

   niech  v  ,  pobierz wartość  ;  v  =  1  ;  funkcja  fa  (  x  )  {  powrót  funkcja  ( )  {  powrót  x  ;  };  };  getValue  =  f  (  v  );  v  =  2  ;  pobierz wartość  ;  // 1 

Ustanawianie prywatnych zmiennych i akcesorów

IIFE są również przydatne do ustanawiania prywatnych metod dla dostępnych funkcji, jednocześnie udostępniając niektóre właściwości do późniejszego wykorzystania. Poniższy przykład pochodzi z postu Almana na temat IIFE.


     
       0

     
           
             
        
           
              
        
            // „licznik” to funkcja, która zwraca obiekt z właściwościami, którymi w tym przypadku są funkcje.  niech  licznik  =  (  funkcja  ()  {  niech  i  =  ;  powrót  {  pobierz  :  funkcja  ()  {  zwróć  ja  ;  },  ustaw  :  funkcja  (  wartość  )  {  i  =  wartość  ;  },  inkrementacja  :  funkcja  ()  { 
             
        
    



       

 
  powrót  ++  i  ;  }  };  })();  // Te wywołania uzyskują dostęp do właściwości funkcji zwróconych przez „counter”.  licznik  .  dostać  ();  // 0  licznik  .  zestaw  (  3  );  licznik  .  przyrost  ();  // 4  liczniki  .  przyrost  ();  // 5 

Jeśli spróbujemy uzyskać dostęp do counter.i ze środowiska globalnego, będzie on niezdefiniowany, ponieważ jest zawarty w wywołanej funkcji i nie jest właściwością counter . Podobnie, jeśli spróbujemy uzyskać dostęp do i , spowoduje to błąd, ponieważ nie zadeklarowaliśmy i w środowisku globalnym.

Terminologia

Pierwotnie znany jako „samoczynna anonimowa funkcja”, Ben Alman wprowadził później obecny termin IIFE jako bardziej dokładną semantycznie nazwę idiomu, wkrótce po tym, jak pojawiła się dyskusja na temat tego idiomu na stronie comp.lang.javascript.

  Warto zauważyć, że natychmiast wywoływane funkcje nie muszą być z natury anonimowe, a tryb ścisły ECMAScript 5 zabrania arguments.callee , czyniąc oryginalny termin mylącym .

Zobacz też

Linki zewnętrzne