2009-06-18 8 views
410

Jaka jest różnica między poniższymi liniami kodu?Jaka jest różnica między wyrażeniem funkcji a deklaracją w kodzie JavaScript?

//Function declaration 
function foo() { return 5; } 

//Anonymous function expression 
var foo = function() { return 5; } 

//Named function expression 
var foo = function foo() { return 5; } 
  • Co to nazwana/anonimowy wyrażenie funkcja?
  • Co to jest zadeklarowana funkcja?
  • W jaki sposób przeglądarki radzą sobie z tymi konstrukcjami w inny sposób?

Co zrobić, aby odpowiedzi na podobne pytanie (var functionName = function() {} vs function functionName() {}) nie były dokładne?

+0

Oto [dobry artykuł na temat nazwanych wyrażeń funkcyjnych] (http://kangax.github.com/nfe). Wyrażenia funkcji kontra deklaracje są adresowane w pierwszej sekcji. –

+0

Główna różnica IMO polega na podnoszeniu. Oto dobry artykuł na ten temat: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html –

Odpowiedz

10

Pierwsze zdanie zależy od kontekstu, w którym zostało zadeklarowane.

Jeśli zostanie zadeklarowany w kontekście globalnym, utworzy domniemaną zmienną globalną zwaną "foo", która będzie zmienną, która wskazuje na funkcję. Zatem wywołanie funkcji "foo()" może być wykonane w dowolnym miejscu w twoim programie javascript.

Jeśli funkcja jest tworzony w zamknięciu stworzy dorozumianą lokalną zmienną o nazwie „foo”, które można następnie wykorzystać do wywołania funkcji wewnątrz zamknięcia z „foo()”

EDIT:

Powinienem też powiedzieć, że instrukcje funkcyjne (Pierwsza) są analizowane przed wyrażeniami funkcyjnymi (Pozostałe 2). Oznacza to, że jeśli zadeklarujesz funkcję na dole skryptu, nadal będziesz mógł używać jej na górze. Wyrażenia funkcyjne są oceniane tylko wtedy, gdy zostaną trafione przez kod wykonawczy.

END EDIT

Oświadczenia 2 & 3 są prawie równoważne do siebie. Ponownie, jeśli zostaną użyte w kontekście globalnym, utworzą zmienne globalne i jeśli zostaną użyte w zamknięciu, zostaną utworzone zmienne lokalne. Warto jednak zauważyć, że instrukcja 3 zignoruje nazwę funkcji, więc można nazwać funkcję cokolwiek. Dlatego

var foo = function foo() { return 5; } 

jest taka sama jak

var foo = function fooYou() { return 5; } 
+19

'fooYou' nie jest ignorowany. Jest widoczny w treści funkcji, więc funkcja może się odwoływać (np. Do implementacji rekursji). –

+1

To dobra uwaga. Nie myślałem o tym :) – Alex

+7

Wyrażenia o nazwanych funkcjach są przydatne do debugowania: 'var foo = function fooYou() {return 5; }; console.log (foo); console.log (foo.name); 'wypisze' fooYou()/fooYou' (Firefox), '[Funkcja: fooYou]/fooYou' (node.js),' function fooYou() {return 5; }/fooYou' (Chrome) lub coś takiego w tych liniach, w zależności od tego, gdzie je wykonujesz. – Gilead

335

Są rzeczywiście bardzo podobny. Sposób ich wywoływania jest dokładnie taki sam. Różnica polega na tym, w jaki sposób przeglądarka ładuje je do kontekstu wykonania.

Deklaracje funkcji ładują się przed wykonaniem dowolnego kodu.

Wyrażenia funkcji ładują się tylko wtedy, gdy interpreter osiągnie ten wiersz kodu.

Więc jeśli spróbujesz wywołać wyrażenie funkcji przed załadowaniem, dostaniesz błąd! Jeśli zamiast tego wywołasz deklarację funkcji, zawsze będzie działać, ponieważ żaden kod nie może zostać wywołany, dopóki nie zostaną załadowane wszystkie deklaracje.

Przykład: Expression Funkcja

alert(foo()); // ERROR! foo wasn't loaded yet 
var foo = function() { return 5; } 

Przykład: deklaracja funkcji

alert(foo()); // Alerts 5. Declarations are loaded before any code can run. 
function foo() { return 5; } 


Co do drugiej części pytania:

var foo = function foo() { return 5; } jest naprawdę sam e jako dwa pozostałe. Po prostu ta linia kodu spowodowała błąd w safari, chociaż już nie.

+23

Ostatnia nie jest tym samym, co '' var foo = function() {return 5; } ''. Ponieważ tutaj, '' foo.name'' to '' '' '', w ostatnim jest '' 'foo'''. – JCM

+2

@JCM AFAIK, właściwość name nie jest częścią ECMAScript i jest zaimplementowana tylko w niektórych przeglądarkach. ['Function.name' w MDN] (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/name) –

+7

@ZachL Właśnie użyłem jako przykładu, co chciałem powiedzieć że druga funkcja ma nazwę, a pierwsza nie. – JCM

1

Chociaż całkowita różnica jest bardziej skomplikowana, jedyną różnicą, która mnie niepokoi, jest to, że maszyna tworzy obiekt funkcji. Co w przypadku deklaracji jest przed wykonaniem jakiejkolwiek instrukcji, ale po wywołaniu ciała oświadczenia (czy to globalnym ciałem kodu, czy podfunkcją), aw przypadku wyrażeń jest, gdy wyciąg zostanie wykonany. Poza tym do wszystkich celów przeglądarki traktują je tak samo.

Aby pomóc ci zrozumieć, spójrz na tę wydajność test, która odrzuciła założenie, że wykonałem zadeklarowane wewnętrznie funkcje, które nie muszą być ponownie tworzone przez urządzenie, gdy wywoływana jest funkcja zewnętrzna. Szkoda też, bo lubiłem pisać kod w ten sposób.

79

deklaracja funkcji

function foo() { ... } 

powodu funkcji podnoszący, funkcja zadeklarowana w ten sposób można nazwać zarówno przed i po definicji.

Expression Funkcja

  1. Nazwany Expression Funkcja

    var foo = function bar() { ... } 
    
  2. Anonymous Funkcja Expression

    var foo = function() { ... } 
    

foo() można wywołać tylko po utworzeniu.

Immediately-Invoked Function Expression (IIFE)

(function() { ... }()); 

Wnioski

Crockforda zaleca stosowanie ekspresji funkcji, ponieważ wyraźnie wskazuje, że foo jest zmienną zawierającą wartość funkcji. Cóż, osobiście wolę używać deklaracji, chyba że istnieje powód do wyrażenia.

+9

Witamy w Stack Overflow! Dziękujemy za przesłanie odpowiedzi! Pamiętaj, aby uważnie przeczytać [FAQ na temat autopromocji] (http://stackoverflow.com/faq#promotion). Należy również pamiętać, że * wymagane * jest to, że publikujesz zrzeczenie się za każdym razem, gdy łączysz się z własną witryną/produktem. –

+1

punkt szczególny: js uwzględnia wielkość liter. Twoje przykłady zamkniętych kapsli nie działają ;-) –

+1

również, możesz * mieć * Nazwany IIFE: '(function myFunc() {...}());' –

17

Odnośnie 3. Definicja:

var foo = function foo() { return 5; } 

Herezje przykład, który pokazuje, jak korzystać z możliwości rekurencyjnego wywołania:

a = function b(i) { 
    if (i>10) { 
    return i; 
    } 
    else { 
    return b(++i); 
    } 
} 

console.log(a(5)); // outputs 11 
console.log(a(10)); // outputs 11 
console.log(a(11)); // outputs 11 
console.log(a(15)); // outputs 15 

Edit: bardziej interesujący przykład z zamknięciami:

a = function(c) { 
return function b(i){ 
    if (i>c) { 
    return i; 
    } 
    return b(++i); 
} 
} 
d = a(5); 
console.log(d(3)); // outputs 6 
console.log(d(8)); // outputs 8 
+7

Nie musisz zadeklarować funkcji o innej nazwie do zrobienia rekurencyjny. W rzeczywistości, powiedziałbym, że myli rzeczy. 'a = funkcja a (i)' i wykonanie 'return a (++ i)' daje taki sam wynik – PhilT

+0

Ale użycie innej nazwy funkcji niż zmiennej ilustruje ten punkt bardziej wyraźnie. Kudos za dostarczenie przykładu użycia nazwanych wyrażeń funkcji. – gfullam

Powiązane problemy