2012-04-10 20 views
46

Powiel możliwe:
JavaScript: var functionName = function() {} vs function functionName() {}Czy nazwane funkcje lub anonimowe funkcje są preferowane w JavaScript?

Istnieją dwa możliwe sposoby wyciągania funkcję w javascript:

var foo = function() { ... } 

(to jest trochę wydumane; inny wspólny wzór jest:

var foo = { 
    baz: 43, 
    doSomething:function() { 
     ... 
    } 
} 

)

kontra

function foo() { ... } 

Czy istnieje wyraźny powód do preferowania jednego lub drugiego?

+0

Czy zakres pierwszej różni się od drugiego? –

+0

To jest fajny artykuł http://kangax.github.com/nfe/ –

+0

@amnotiam: uzgodniono. Zagłosowano, aby zamknąć. –

Odpowiedz

66

Wszystko sprowadza się do wyboru miejsca, w którym deklarujesz swoje funkcje; podnoszenie.

Deklaracje funkcji i deklaracje zmiennych są zawsze przenoszone ("wyciągnięte") niewidocznie na górę ich zakresu zawartości przez interpreter JavaScript. Parametry funkcji i nazwy zdefiniowane w języku są już oczywiście. Oznacza to, że kodu:

function foo() { 
    bar(); 
    var x = 1; 
} 

jest właściwie interpretować tak:

function foo() { 
    var x; 
    bar(); 
    x = 1; 
} 

Zauważ, że część przyporządkowanie zgłoszeń nie były podnoszone. Tylko nazwa jest podniesiona. Nie dzieje się tak w przypadku deklaracji funkcji, w których cały korpus funkcji również zostanie podniesiony.

function test() { 
    foo(); // TypeError "foo is not a function" 
    bar(); // "this will run!" 
    var foo = function() { // function expression assigned to local variable 'foo' 
     alert("this won't run!"); 
    } 
    function bar() { // function declaration, given the name 'bar' 
     alert("this will run!"); 
    } 
} 
test(); 

W tym przypadku tylko deklaracja funkcji ma swoje ciało podniesione do góry. Nazwa "foo" jest podnoszona, ale ciało zostaje w tyle, aby zostać przydzielone podczas egzekucji.

można nadać nazwy funkcji określonych w wyrażeniach funkcyjnych ze składnią jak deklaracja funkcji. Nie oznacza to, że jest to deklaracja funkcji, a nazwa nie jest wprowadzana w zakres, ani nie jest podniesione ciało.

foo(); // TypeError "foo is not a function" 
bar(); // valid 
baz(); // TypeError "baz is not a function" 
bin(); // ReferenceError "bin is not defined" 

var foo = function() {}; // anonymous function expression ('foo' gets hoisted) 
function bar() {}; // function declaration ('bar' and the function body get hoisted) 
var baz = function bin() {}; // named function expression (only 'baz' gets hoisted) 

foo(); // valid 
bar(); // valid 
baz(); // valid 
bin(); // ReferenceError "bin is not defined" 

Dlatego, jeśli preferencja ma mieć funkcje podnosić na górę Użyj function declaration inaczej używać expression. Wolę ten drugi jak zwykle budować literały obiektu z metodami jak function expressions.

Nazwany function expressions może być przydatna, gdy błędy są wyrzucane. Konsola powie, co funkcja jest zamiast stwierdzając anonymous aka ślad stosu.

+4

Pamiętaj tylko, że deklaracje funkcji w blokach są [technicznie nieważne] (http://stackoverflow.com/questions/4071292/may-function-declarations-appear-inside-statements-in-javascript), więc może być preferowane użycie Wyrażenia funkcyjne. –

+1

Wow, jest tak oczywiste, że "deklaracje funkcji" nie powinny istnieć/być traktowane specjalnie w javascript - powinny być po prostu wyrażeniem, jak "nazwane wyrażenie funkcji", którego wartość zwracana jest ignorowana. – masterxilo

+0

@ JesseDobko-ah tak, mam na myśli wewnątrz * jeśli * blokuje. Naprawię to. – RobG

3

Istnieje kilka zalet do nazewnictwa funkcji

  • nazwy dla analizy meta. functionInstance.name pokaże Ci nazwę.
  • Daleko ważniejsze, nazwa zostanie wydrukowany w ślady stosu.
  • nazwy pomagają również pisać dokumentację własną lub pisać kod.

jest tylko jeden wadą wymienionych funkcji wyrażenia

  • IE ma wycieków pamięci dla NFE

Brak wady funkcjonować deklaracji oprócz mniejszej stylistycznej kontroli

+0

Jakie wersje programu IE? 9? –

+0

IE <9. Starsze silniki JScript, także Saf 2.1, Stara opera, stary firefox. Przeczytaj artykuł NFE – Raynos

0

Twój Pytanie naprawdę składa się z dwóch części, ponieważ niekoniecznie musisz uczynić swoje funkcje anonimowymi, jeśli są one przypisane do zmiennej lub własności.

Nazwany kontra anonimowy?

@Raynos wyraźnie podkreśla główne punkty. Najlepszą rzeczą w nazwanych funkcjach jest to, że będą się wyświetlać w śladach stosu. Nawet w sytuacjach, w których funkcje są przypisane do zmiennych/właściwości, dobrze jest nadać swoim funkcjom nazwę tylko po to, by pomóc w debugowaniu, jednak nie powiedziałbym, że anonimowe funkcje są w ogóle złe. Robią serwujemy wyśmienite cel: oświadczenie

Are anonymous functions a bad practice in JavaScript?

Function vs wypowiedzi funkcja?

Dla tej części pytanie chciałbym skierować do tej kwestii, gdyż prawdopodobnie pokrywa temat w znacznie większej głębokości niż mogę

var functionName = function() {} vs function functionName() {}

9

pan trafić na kilka różnych rzeczy tutaj , ale najpierw spróbuję odpowiedzieć na twoje główne pytanie.

Ogólnie ....

function() { ... } jest wyrażeniem funkcja. Składnie to jest na tym samym poziomie co 2 lub [4,5]. To reprezentuje wartość o wartości. Czynienie var foo=function(){ ... } będzie działać zgodnie z planem, za każdym razem.

function foo() { ... } jest deklaracją funkcji. Może wydawać się, że robi to samo, co var foo=function(){...}, ale istnieje małe zastrzeżenie. Jako deklaracja działa podobnie do pojęcia zmiennego podnoszenia w JS (zasadniczo wszystkie deklaracje zmiennych są wykonywane przed wyliczeniem dowolnych wyrażeń).

Dobrym przykładem jest z here:

function test() { 
    foo(); // TypeError "foo is not a function" 
    bar(); // "this will run!" 
    var foo = function() { // function expression assigned to local variable 'foo' 
     alert("this won't run!"); 
    } 
    function bar() { // function declaration, given the name 'bar' 
     alert("this will run!"); 
    } 
} 
test(); 

Zasadniczo zmienna podnoszenia dało wartość do góry, tak, że kod jest równa (teoretycznie) do:

function test() { 
    var foo;//foo hoisted to top 
    var bar=function(){//this as well 
     alert("this will run!"); 
    } 

    foo(); // TypeError "foo is not a function" 
    bar(); // "this will run!" 
    var foo = function() { // function expression assigned to local variable 'foo' 
     alert("this won't run!"); 
    } 
} 

NB: Chciałbym zabrać to miejsce, aby powiedzieć, że tłumacze JS mają trudności z podążaniem za teorią, więc ufając im nieco niepewnym zachowaniom r nie jest zalecane.Here znajdziesz dobry przykład na końcu sekcji, gdzie teoria i praktyka w końcu nie działają (są też trochę więcej szczegółów na temat wyrażeń w porównaniu do deklaracji).

Ciekawostka: owijanie function foo() {...} w nawiasach przekształca go z deklaracją do ekspresji, co może prowadzić do pewnego dziwne patrząc kodu jak

(function foo() { return 1; })();// 1 
foo; //ReferenceError: foo is not defined 

Nie rób tego, jeśli nie mają powód do , Proszę.


Podsumowanievar foo=function(){ ... } jest * jakoś trochę * taka sama jak funkcja foo(){ ... } tą różnicą, że były robi to, co myślisz, że to robi, gdzie myślisz, że powinien natomiast druga ma dziwne rzeczy, chyba że zawinąć go w parens, ale to tłumaczy zakres, a tłumacze JS pozwalają ci robić rzeczy, które są uważane za błędy składniowe w specyfikacji, więc jesteś przekonany, że złe rzeczy są w rzeczywistości słuszne, itp.

użyj funkcji wyrażenia (var f=function(){...}). Nie ma prawdziwego powodu, aby tego nie robić, szczególnie biorąc pod uwagę, że jesteście do tego zmuszeni, kiedy używacie składni kropek.


do drugiego rzeczą, którą dotknął .....

Nie jestem pewien, co powiedzieć, to trochę jakoś zupełnie inna od wszystkiego innego na ten temat.

var foo = { 
    baz: 43, 
    doSomething:function() { 
     ... 
    } 
} 

jest to tak zwana składnia literalna obiektu. JSON, który jest oparty na tej składni, to a pretty neat way of formatting data, a ta składnia w JS jest często używana do deklarowania nowych obiektów, na przykład z obiektami singleton (unikanie całego bałaganu z deklarowaniem funkcji i używaniem nowych). Może być również stosowany w taki sam sposób XML jest używany i jest preferowane przez wszystkich fajnych dzieciaków ...

Tak czy inaczej, w zasadzie sprzeciwu składnia dosłowne działa tak:

{ name1: val1, .... namek:valk } 

To wyrażenie jest obiektem z zainicjowanymi na nim pewnymi wartościami. Czyniąc var obj={ name1: val1, .... namek:valk } oznacza, że:

obj.name1==val1; 
obj['name1']==val1;// x['y'] is the same thing as x.y 
... 
obj.namek==valk; 

Więc co to ma wspólnego z naszym przykładzie? Zasadniczo twoja ekspresja jest często używana do zadeklarowania pojedynczych obiektów. Ale może być również użyty do zadeklarowania prototypu obiektu, więc ktoś może później zrobić var ​​newObj = Object.create (foo), a newObj będzie mieć foo jako prototyp.

Spójrz szczegółowo na prototypowe dziedziczenie, jeśli naprawdę chcesz uzyskać przydatność. Douglas Crockford mówi o nim szczegółowo w swoich licznych rozmowach one).

+0

Przykład 'var foo = {...' nie jest składnią JSON. To literalna składnia obiektu. Notowania struktury danych JSON * bazują na * obiekcie JavaScript i strukturach literowych, ale nie są tym samym. –

+0

zauważyłem, próbowałem poprawnie zmienić odniesienia do JSON. Czy masz przykład JSON, który nie jest prawidłową składnią literalną lub vise versa? – rtpg

+0

Generalnie, jeśli definiujesz literał obiektu w kodzie JavaScript, nie nazywamy go JSON, ponieważ reszta kodu JS powoduje, że jest on nieprawidłowy JSON. I odwrotnie, jeśli usuniemy wszystkie JS i po prostu mamy niezależną strukturę JSON, taką jak '{" foo ":" bar "}' (ponieważ klucze JSON muszą być podwójnie cytowane), to nie jest to poprawny program JavaScript. Rezultatem będzie * SyntaxError *. Ponadto są pewne niewidoczne znaki, które są dozwolone w łańcuchach JavaScript, ale nie JSON. Ogólnie rzecz biorąc, jedyne połączenie między JS i JSON to dwie pierwsze litery i * ogólna * składnia struktur danych. –

Powiązane problemy