2010-09-26 9 views
8

Wiem, że istnieje kilka sposobów definiowania funkcji w JavaScript. Dwa z najczęstszych należą:Co się dzieje w JavaScript, gdy używam "tradycyjnej" deklaracji funkcji w stylu C?

(1) function add (a, b) { 
     return a + b; 
    } 

(2) var add = function (a, b) { 
     return a + b; 
    } 

jestem wygodne z ideą funkcji jako obiektu, który może zostać przekazany wokół podobnie jak każdej innej zmiennej. Rozumiem doskonale, co robi (2). Tworzy funkcję i przypisuje ją do add (załóżmy, że jest to zakres globalny, więc add jest zmienną globalną) wspomnianej funkcji. Ale co się dzieje, jeśli zamiast tego używam (1)? Wiem już, że robi to różnicę w kolejności wykonywania: jeśli używam (1), mogę odnieść się do add() przed punktem w kodzie, w którym zdefiniowano add(), ale jeśli używam (2), muszę przypisać moją funkcję do add, zanim będę mógł rozpocznij, odnosząc się do add().

Czy (1) jest skrótem do (2), ale zachowuje się tak, jak inne języki w stylu C, pozwalając nam zdefiniować funkcję "poniżej" punktu, w którym jest używana? Czy jest wewnętrznie inny rodzaj funkcji? Który jest bardziej "w duchu" JavaScript (jeśli to nie jest zbyt niejasne określenie)? Czy ograniczyłbyś się do jednego lub drugiego, a jeśli tak, który?

Odpowiedz

6

Wygląda na to są już świadomi głównych cech function declarations (1) i function expressions (2). Należy również pamiętać, że w (1) wciąż jest zmienna lokalna o nazwie add zawierającym wartości funkcji, podobnie jak w (2):

function hello() { 
    alert('Hello World'); 
} 

console.log(typeof hello); // prints "function" 

setTimeout(hello, 1000); // you can still pass functions around as arguments, 
          // even when using function declarations. 

Jeden inny punkt warto wspomnieć, że deklaracje funkcji (1) powinnaś • należy użyć do zdefiniowania funkcji warunkowo (np. w instrukcjach if), ponieważ, jak już wspomniano, są one automatycznie przenoszone na początek zakresu zawartości za pomocą interpretera JavaScript . Jest to zwykle określane jako hoisting.

Co do tego, które podejście jest bardziej zgodne z duchem JavaScript, wolę używać wyrażeń funkcji (2). Aby uzyskać bardziej wiarygodną opinię, Douglas Crockford zawiera listę deklaracji funkcji (1) w rozdziale "Złe części" w jego popularnym The Good Parts book .


znany również jako sprawozdania funkcyjnych (Zobacz @Tim Down's komentarze poniżej).
W rzeczywistości niektóre przeglądarki mogą obsługiwać deklaracje funkcji w instrukcjach if (Ponownie odwołać się do komentarzy poniżej).
JavaScript: The Good Parts - Dodatek B: Strona 113.

+2

Deklaracja funkcji w bloku instrukcji "if" jest błędem składni, zgodnie ze specyfikacją ECMAScript. Żadna z głównych przeglądarek nie zgłasza błędu, prawdopodobnie z powodu precedensu ustawionego przez IE i Mozillę. Mozilla obejmie go przez dodanie rozszerzenia do ECMAScript zwanego 'FunctionStatement' (http://www.jibbering.com/faq/#functionStatement, http://kangax.github.com/nfe/#function-statements). JScript ma mniej szacunku dla specyfikacji i wie, co Bóg wie. –

+1

Komentarz do edycji: to prawda, że ​​deklaracje funkcji są również określane jako instrukcje funkcji, ale niepoprawnie. Często zadawane pytania na temat comp.lang.javascript (powiązane z moim poprzednim komentarzem) bardzo wymownie brzmią: * "Określenie funkcji function zostało szeroko i niesłusznie użyte do opisania" FunctionDeclaration ". Jest to mylące, ponieważ w ECMAScript:" FunctionDeclaration " 'nie jest' Statement', są miejsca w programie, w których 'Statement' jest dozwolony, ale' FunctionDeclaration' nie jest. "* –

+0

@Tim: Dzięki za interesujące komentarze. Nie wiedziałem o problemie nazewnictwa "oświadczenia". –

2
function foo() {}; 
foo.toString() //-> "function foo() {}" 

var bar = foo; 
bar.toString() //-> "function foo() {}" 

więc deklaruje nazwie funkcji. Bez względu na to, która zmienna wskazuje na to, nazwa jest zachowywana.Używanie innej składni jest funkcją anonimową, która jest bezimienna i może być dostępna tylko wtedy, gdy odwołuje się do niej zmienna.

var foo = function() {}; 
foo.toString() //-> "function() {}" 

var bar = foo; 
bar.toString() //-> "function() {}" 

Jeśli chodzi o styl, nie ma większej zasady. Chociaż osobiście faworyzuję anonimową składnię, ponieważ przypomina mi, że funkcje są rzeczywiście obiektami, które można przekazywać. Ja również preferuję podejście "to wszystko w dużym obiekcie głównym", które wymaga, aby funkcje były zadeklarowane w ten sposób.

var MyThingy = { 
    foo: function() { alert('foo') }, 
    bar: function() { MyThingy.foo() } 
} 

Ale po utworzeniu funkcji różnice nie są tak naprawdę ważne i zachowują się tak samo. Ale anonimowa składnia ma mniej tego skanu przed magią, o której wspomniałeś, a także mniej błędów w skomplikowanym kodzie i dziwnych sytuacjach dotyczących zakresu.

Powiązane problemy