Deklaracja funkcji jako var zamiast funkcji

28

Coraz więcej widzę, jak funkcje są deklarowane jak

var foo = function() {

    // things
};

Zamiast tego, jak się nauczyłem

function foo() {

    // things
}

Co za różnica? Lepsza wydajność? Zakres? Czy powinienem używać tej metody?

Steve Robbins
źródło
warto zauważyć, że w javascript funkcje są pierwszorzędnymi obywatelami . Umożliwia to przekazywanie zachowań tak jak obiektów. Jest to bardzo przydatne między innymi do połączeń zwrotnych i delegacji.
Chris Bye
Zakres . Zawijanie nazw zmiennych „// rzeczy” zasadniczo / miejmy nadzieję zapobiega kolizjom nazw „// rzeczy”, które są zawijane, wraz z innymi JavaScript (plikami). Innym sposobem myślenia o tym jest utworzenie przestrzeni nazw „foo”.
radarbob

Odpowiedzi:

25

var foo = function() {} definiuje zmienną, która odwołuje się do funkcji anonimowej.

function foo() {}definiuje nazwaną funkcję foo.

Każda z nich może zostać przekazana przez nazwę jako parametry funkcji i może zostać utworzona instancja, jeśli zamierzone użycie dotyczy OOP.

Na koniec dnia, którego używasz, jest w dużej mierze podyktowane konkretnym przypadkiem użycia (Javascript jest taki zabawny;)). Jeśli w końcu użyjesz tego pierwszego, zdecydowanie sugeruję, abyś nazwał funkcję:

var foo = function MY_function() {}. Ta konwencja nazewnictwa pomaga, aby zestaw wywołań debuggera nie był bezużyteczny.

Demian Brecht
źródło
1
Mam goof na funkcji () MY ...
Erik Reppen,
1
@Demian Brecht, a co z podejściem var foo = function foo () {...}?
shabunc
@shabunc: Co z tym? Jest wymieniony w ostatnim akapicie mojej odpowiedzi.
Demian Brecht
@Demian Brecht, nie, tak naprawdę w ostatnim akapicie wywoływana jest zmienna fooi wywoływana jest funkcjaMY_function
shabunc
@shabunc: Nazwa nie ma znaczenia. Liczy się wartość w callstacku. Na przykład [NAMESPACE] _ [nazwa fn] to konwencja używana przez Mozillę. Sama nazwa nie ma znaczenia, o ile konwencja jest spójna w całym projekcie.
Demian Brecht
13

wyrażenie funkcji:

//someFunction(); //wouldn't work when uncommented
var someFunction = function(){ alert('yay'); };

Wyrażenie func w tym przypadku jest anonimowe, ale przypisane do var dla odniesienia. Różni się to od instrukcji funkcji oznaczonej etykietą w następujący sposób:

  • nie można go podnieść (wywoływany przed zdefiniowaniem)
  • new someFunction().constructor.name === 'someFunction';//false instancje nie otrzymują nazwy zmiennej dla konstruktora.nazwa, ponieważ odwołanie do funkcji jest przypisane do zmiennej, ale zmienna, a nie funkcja, jest powiązana z nazwą zmiennej

W oznaczonej instrukcji funkcji:

//someFunction(); //works when uncommented
function someFunction(){ alert('yay'); }
  • prace dźwigowe
  • new someFunction().constructor.name === 'someFunction'; //true nazwa jest bezpośrednio powiązana z funkcją.

Ogólnie rzecz biorąc, nie ma naprawdę wielkiego powodu, aby używać wyrażenia do var, chyba że chcesz, aby wywołania kończyły się niepowodzeniem, jeśli sprawy się zmieniają lub definiujesz / przypisujesz metodę w jednej linii. Uważam, że podnoszenie jest przydatne do organizowania obiektów z wewnętrznymi funkcjami i definicjami metod na dole, dzięki czemu mogę przejść do faktycznego zachowania obiektu i wykonać jednowierszowe definicje metod publicznych (po prostu przypisując funcs do this.tej samej nazwy) wszystko w jednym miejsce dla ułatwienia odniesienia. Zawsze powinieneś próbować używać oznaczonych instrukcji dla konstruktorów, IMO, abyś mógł zidentyfikować „typ” obiektu za pomocą jego konstruktora.

Erik Reppen
źródło
8

Twój pierwszy przykład jest wyrażeniem, a drugi przykład jest wyrażeniem . Definiowanie funkcji jako wyrażeń pozwala na większą elastyczność w tym, gdzie może wystąpić definicja, do czego można ją przypisać, że można przekazać ją jako parametr itp.

Na przykład:

SomeThing('abc', function(a,b) {return a*b;});

vs...

function tmp(a,b) { 
    return a*b;
}

SomeThing('abc', tmp);

Bardziej złożone przykłady stałyby się nieprzyzwoicie skomplikowane bez składni wyrażenia funkcji.

Spójrz na https://stackoverflow.com/questions/111102/how-do-javascript-closures-work

gahooa
źródło
4

Główną praktyczną różnicą jest podnoszenie. Na przykład:

foo(); // alerts 'hello'
function foo() {alert('hello');}

vs

foo(); // throws an error since foo is undefined
var foo = function() {alert('hello');}

Jest to również niezdefiniowane zachowanie

function foo(){
  if (true) {
    function bar(){}
  }
  bar();
}

podczas gdy to jest w porządku.

function foo(){
  if (true) {
    var bar = function(){}
  }
  bar();
}
Austin
źródło
7
Nie ma absolutnie nic złego w definiowaniu funkcji wewnątrz funkcji w JS. Nie ma wielu miejsc, w których nie można zdefiniować funkcji w JS.
Erik Reppen,
2
@ErikReppen Zdecydowanie nie można używać deklaracji funkcji w blokach niefunkcjonalnych (jak w instrukcji if). Nie mogę znaleźć miejsca, w którym czytam, że nie można ich używać w ramach innej funkcji.
Austin
@Austin Nie ma nic złego w definicji funkcji w ifinstrukcji!
Tim
@Austin: Być może przeczytałeś to na w3schools? ;)
Demian Brecht
2
@ErikReppen Wyrażeń funkcyjnych można używać w dowolnym miejscu. Deklaracje funkcji nie mogą być. Zobacz stackoverflow.com/questions/10069204/...
Austin