38 Pytanie: var functionName = function () {} vs function functionName () {}

pytanie utworzone w Mon, Apr 15, 2019 12:00 AM

Niedawno zacząłem utrzymywać kod JavaScript innej osoby. Naprawiam błędy, dodam funkcje, a także staram się uporządkować kod i uczynić go bardziej spójnym.

Poprzedni programista używa dwóch sposobów deklarowania funkcji i nie mogę się zorientować, czy za tym stoi powód.

Istnieją dwa sposoby:

 
var functionOne = function() {
    // Some code
};
 
function functionTwo() {
    // Some code
}

Jakie są powody korzystania z tych dwóch różnych metod i jakie są zalety i wady każdego z nich? Czy jest coś, co można zrobić za pomocą jednej metody, której nie można zrobić z drugą?

    
6485
  1. permadi.com/tutorial /jsFunc/index.html to bardzo dobra strona dotycząca funkcji JavaScript
    2010-04-09 11: 51: 59Z
  2. Powiązany jest ten doskonały artykuł o Nazwane wyrażenia funkcji .
    2011-04-21 21: 30: 10Z
  3. @ CMS odwołuje się do tego artykułu: kangax.github.com/nfe/#expr-vs-decl
    2011-08-03 14: 18: 43Z
  4. Są dwie rzeczy, o których należy pamiętać: # 1 W JavaScript deklaracje są podnoszone. Oznacza to, że var a = 1; var b = 2; staje się var a; var b; a = 1; b = 2. Więc kiedy deklarujesz funkcję One, zostaje ona zadeklarowana, ale jej wartość nie jest ustawiana natychmiast. Podczas gdy funkcja functionTwo jest tylko deklaracją, zostaje umieszczona na szczycie zakresu. # 2 functionTwo pozwala uzyskać dostęp do właściwości name i to bardzo pomaga przy próbie debugowania czegoś.
    2012-08-21 16: 20: 22Z
  5. Oh i btw, poprawna składnia jest z ";" po przydzieleniu i bez zgłoszenia. Na przykład. function f(){} vs var f = function(){};.
    2012-08-21 16: 27: 11Z
30 odpowiedzi                              30                         

Różnica polega na tym, że functionOne jest wyrażeniem funkcji, a więc jest definiowane tylko wtedy, gdy linia jest osiągnięta, podczas gdy functionTwo jest deklaracją funkcji i jest definiowana, gdy tylko zostanie wykonana otaczająca funkcja lub skrypt (z powodu podnoszenie ).

Na przykład wyrażenie funkcji:

 
// TypeError: functionOne is not a function
functionOne();

var functionOne = function() {
  console.log("Hello!");
};

I deklaracja funkcji:

 
// Outputs: "Hello!"
functionTwo();

function functionTwo() {
  console.log("Hello!");
}

Oznacza to również, że nie można warunkowo definiować funkcji za pomocą deklaracji funkcji:

 
if (test) {
   // Error or misbehavior
   function functionThree() { doSomething(); }
}

Powyższe faktycznie definiuje functionThree niezależnie od wartości test - chyba że obowiązuje use strict, w takim przypadku po prostu wywołuje błąd.

    
4805
2018-05-15 09: 03: 16Z
  1. @ Greg: Przy okazji, różnica nie polega tylko na tym, że są one analizowane w różnych momentach. Zasadniczo, twoja functionOne jest jedynie zmienną, do której przypisana jest funkcja anonimowa, podczas gdy functionTwo jest w rzeczywistości funkcją nazwaną. Zadzwoń pod .toString(), aby zobaczyć różnicę. Jest to istotne w niektórych przypadkach, gdy chcesz uzyskać nazwę funkcji programowo.
    2011-08-05 21: 18: 09Z
  2. @ Jason Bunting .. nie jestem pewien, co tu robisz, .toString () wydaje się zwracać zasadniczo tę samą wartość (definicja funkcji) dla obu: cl.ly/2a2C2Y1r0J451o0q0B1B
    2011-09-09 16: 29: 42Z
  3. Oba są różne. Pierwszy to function expression, drugi to function declaration. Możesz przeczytać więcej na ten temat tutaj: javascriptweblog. wordpress.com/2010/07/06/…
    2011-11-14 06: 03: 31Z
  4. @ Greg Część twojej odpowiedzi dotycząca czasu analizowania w porównaniu z czasem wykonywania jest niepoprawna. W JavaScript deklaracje funkcji nie są definiowane w czasie analizy, ale w czasie wykonywania. Proces przebiega w ten sposób: Kod źródłowy jest analizowany - > Program JavaScript jest oceniany - > Kontekst wykonania globalnego jest inicjowany - > wykonywane jest tworzenie powiązania deklaracji. Podczas tego procesu deklaracje funkcji są inicjowane (patrz krok 5 Rozdział 10.5 ). div>
    2012-01-04 00: 59: 56Z
  5. Terminologia dotycząca tego zjawiska jest znana jako podnoszenie.
    2013-01-03 07: 22: 33Z

Najpierw chcę poprawić Greg: function abc(){} ma również zasięg - nazwa abc jest zdefiniowana w zakresie, w którym ta definicja została napotkana. Przykład:

 
function xyz(){
  function abc(){};
  // abc is defined here...
}
// ...but not here

Po drugie, możliwe jest połączenie obu stylów:

 
var xyz = function abc(){};

xyz będzie zdefiniowane jak zwykle, abc jest niezdefiniowane we wszystkich przeglądarkach, ale Internet Explorer - nie polegaj na tym, że jest zdefiniowane. Ale zostanie zdefiniowane wewnątrz jego ciała:

 
var xyz = function abc(){
  // xyz is visible here
  // abc is visible here
}
// xyz is visible here
// abc is undefined here

Jeśli chcesz aliasować funkcje we wszystkich przeglądarkach, użyj tego rodzaju deklaracji:

 
function abc(){};
var xyz = abc;

W tym przypadku zarówno xyz, jak i abc są aliasami tego samego obiektu:

 
console.log(xyz === abc); // prints "true"

Jednym z istotnych powodów używania stylu łączonego jest atrybut „nazwa” obiektów funkcyjnych ( nieobsługiwany przez program Internet Explorer ). Zasadniczo, gdy definiujesz funkcję taką jak

 
function abc(){};
console.log(abc.name); // prints "abc"

jego nazwa jest automatycznie przypisywana. Ale kiedy zdefiniujesz to jak

 
var abc = function(){};
console.log(abc.name); // prints ""

jego nazwa jest pusta - stworzyliśmy funkcję anonimową i przypisaliśmy ją do jakiejś zmiennej.

Innym dobrym powodem użycia stylu łączonego jest użycie krótkiej nazwy wewnętrznej do odwoływania się do samego siebie, zapewniając jednocześnie długą, nie powodującą konfliktów nazwę dla użytkowników zewnętrznych:

 
// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
  // Let it call itself recursively:
  shortcut(n - 1);
  // ...
  // Let it pass itself as a callback:
  someFunction(shortcut);
  // ...
}

W powyższym przykładzie możemy zrobić to samo z zewnętrzną nazwą, ale będzie ona zbyt nieporęczna (i wolniejsza).

(Innym sposobem na odwołanie się do niego jest użycie arguments.callee, które jest wciąż stosunkowo długie i nie jest obsługiwane w trybie ścisłym).

W głębi, JavaScript traktuje obie instrukcje inaczej. To jest deklaracja funkcji:

 
function abc(){}

abc tutaj jest zdefiniowane wszędzie w bieżącym zakresie:

 
// We can call it here
abc(); // Works

// Yet, it is defined down there.
function abc(){}

// We can call it again
abc(); // Works

Podniosło się również do return:

 
// We can call it here
abc(); // Works
return;
function abc(){}

To jest wyrażenie funkcji:

 
var xyz = function(){};

xyz tutaj jest zdefiniowany z punktu przypisania:

 
// We can't call it here
xyz(); // UNDEFINED!!!

// Now it is defined
xyz = function(){}

// We can call it here
xyz(); // works

Deklaracja funkcji a wyrażenie funkcji to prawdziwy powód, dla którego Greg pokazuje różnicę.

Zabawny fakt:

 
var xyz = function abc(){};
console.log(xyz.name); // Prints "abc"

Osobiście wolę deklarację „wyrażenie funkcji”, ponieważ w ten sposób mogę kontrolować widoczność. Kiedy zdefiniuję funkcję taką jak

 
var abc = function(){};

Wiem, że zdefiniowałem tę funkcję lokalnie. Kiedy zdefiniuję funkcję taką jak

 
abc = function(){};

Wiem, że zdefiniowałem to globalnie, pod warunkiem, że nie zdefiniowałem abc w dowolnym miejscu łańcucha zakresów. Ten styl definicji jest odporny nawet wtedy, gdy jest używany wewnątrz eval(). Podczas gdy definicja

 
function abc(){};

zależy od kontekstu i może spowodować, że zgadniesz, gdzie jest ono zdefiniowane, zwłaszcza w przypadku eval() - odpowiedź brzmi: zależy od przeglądarki.

    
1880
2016-10-10 20: 38: 55Z
  1. Odnoszę się do RoBorg, ale nigdzie go nie ma. Proste: RoBorg === Greg. W ten sposób historia może być przepisana w dobie internetu. ;-)
    2009-07-26 02: 52: 14Z
  2. var xyz = function abc () {}; console.log (xyz === abc); Wszystkie przeglądarki, które przetestowałem (Safari 4, Firefox 3.5.5, Opera 10.10) dają mi„ Niezdefiniowaną zmienną: abc ” .
    2009-12-03 17: 43: 04Z
  3. Ogólnie myślę, że ten post dobrze wyjaśnia różnice i zalety korzystania z deklaracji funkcji. Zgodzę się nie zgodzić, jeśli chodzi o korzyści wynikające z wykorzystania przypisań funkcji do zmiennej, zwłaszcza że „korzyść” wydaje się być zaleceniem deklarowania globalnej jednostki ... i wszyscy wiedzą, że nie należy zaśmiecać globalnej przestrzeni nazw , dobrze? ;-)
    2013-10-08 16: 30: 28Z
  4. imo Ogromnym powodem używania nazwanej funkcji jest to, że debuggery mogą używać nazwy, aby pomóc ci zrozumieć sens stosu wywołań lub śledzenia stosu. jest do bani, gdy patrzysz na stos wywołań i widzisz „anonimową funkcję” 10 poziomów głęboko ...
    2014-01-26 18: 25: 18Z
  5. var abc = function(){}; console.log(abc.name); już nie produkuje "", ale "abc" zamiast tego.
    2018-05-04 12: 49: 49Z

Oto przegląd standardowych formularzy tworzących funkcje: (pierwotnie napisany dla innego pytania, ale dostosowany po przeniesieniu do pytania kanonicznego.)

Warunki:

Szybka lista:

  • Deklaracja funkcji

  • „Anonimowy” function Wyrażenie (które mimo terminu czasami tworzy funkcje z nazwami)

  • Nazwany function Wyrażenie

  • Inicjator funkcji dostępu (ES5 +)

  • Strzałka Wyrażenie funkcji (ES2015 +) (które, podobnie jak wyrażenia funkcji anonimowych, nie zawiera wyraźnej nazwy, a mimo to może tworzyć funkcje z nazwami)

  • Deklaracja metody w inicjatorze obiektu (ES2015 +)

  • Deklaracje konstruktora i metody w class (ES2015 +)

Deklaracja funkcji

Pierwsza forma to deklaracja funkcji , która wygląda następująco:

 
function x() {
    console.log('x');
}

Deklaracja funkcji jest deklaracją ; to nie jest oświadczenie ani wyrażenie. Jako taki nie śledzisz go za pomocą ; (chociaż jest to nieszkodliwe).

Deklaracja funkcji jest przetwarzana, gdy wykonanie wchodzi w kontekst, w którym się pojawia, zanim zostanie wykonany dowolny kod krok po kroku. Funkcja, którą tworzy, otrzymuje poprawną nazwę (x w powyższym przykładzie), a nazwa ta jest umieszczana w zakresie, w jakim pojawia się deklaracja.

Ponieważ jest przetwarzany przed dowolnym kodem krok po kroku w tym samym kontekście, możesz robić takie rzeczy:

 
x(); // Works even though it's above the declaration
function x() {
    console.log('x');
}

Do ES2015 specyfikacja nie obejmowała tego, co powinien zrobić silnik JavaScript, jeśli umieścisz deklarację funkcji wewnątrz struktury kontrolnej, takiej jak try, if, switch, while itp. w następujący sposób:

 
if (someCondition) {
    function foo() {    // <===== HERE THERE
    }                   // <===== BE DRAGONS
}

A ponieważ są one przetwarzane przed uruchamianiem kodu krok po kroku, trudno jest wiedzieć, co robić, gdy są w strukturze kontrolnej.

Chociaż wykonanie tego nie było określone do ES2015, to dozwolone rozszerzenie obsługiwało deklaracje funkcji w blokach. Niestety (i nieuchronnie) różne silniki robiły różne rzeczy.

W ES2015 specyfikacja mówi, co robić. W rzeczywistości daje trzy różne rzeczy do zrobienia:

  1. Jeśli w trybie luźnym nie w przeglądarce internetowej, silnik JavaScript ma zrobić jedną rzecz
  2. Jeśli w trybie luźnym w przeglądarce internetowej, silnik JavaScript ma zrobić coś innego
  3. Jeśli w trybie ścisłym (przeglądarka lub nie), silnik JavaScript ma zrobić jeszcze jedną rzecz

Reguły dla luźnych trybów są trudne, ale w trybie ścisłym deklaracje funkcji w blokach są łatwe: są lokalne względem bloku (mają zasięg bloku , co również jest nowością w ES2015), i są one podnoszone na szczyt bloku. Więc:

 
"use strict";
if (someCondition) {
    foo();               // Works just fine
    function foo() {
    }
}
console.log(typeof foo); // "undefined" (`foo` is not in scope here
                         // because it's not in the same block)

„Anonimowy” function Wyrażenie

Drugi wspólny formularz nazywany jest wyrażeniem funkcji anonimowej :

 
var y = function () {
    console.log('y');
};

Podobnie jak wszystkie wyrażenia, jest oceniany, gdy zostanie osiągnięty w wykonaniu kodu krok po kroku.

W ES5 funkcja, którą tworzy, nie ma nazwy (jest anonimowa). W ES2015 do funkcji przypisano nazwę, jeśli to możliwe, wywodząc ją z kontekstu. W powyższym przykładzie nazwa będzie wynosić y. Coś podobnego robi się, gdy funkcja jest wartością inicjatora właściwości. (Aby uzyskać szczegółowe informacje na temat tego, kiedy to się dzieje i reguł, wyszukaj SetFunctionName w specyfikacji - pojawia się all miejsce.)

Nazwany function Wyrażenie

Trzeci formularz to nazwane wyrażenie funkcji („NFE”):

 
var z = function w() {
    console.log('zw')
};

Funkcja, którą tworzy, ma właściwą nazwę (w tym przypadku w). Podobnie jak wszystkie wyrażenia, jest to oceniane, gdy zostanie osiągnięte w wykonaniu kodu krok po kroku. Nazwa funkcji jest nie dodana do zakresu, w którym pojawia się wyrażenie; nazwa jest w zakresie samej funkcji:

 
var z = function w() {
    console.log(typeof w); // "function"
};
console.log(typeof w);     // "undefined"

Zauważ, że NFE często były źródłem błędów dla implementacji JavaScript. IE8 i wcześniejsze, na przykład, obsługują NFE całkowicie niepoprawnie , tworząc dwa różne działa w dwóch różnych momentach. Wcześniejsze wersje Safari miały również problemy. Dobrą wiadomością jest to, że obecne wersje przeglądarek (IE9 i nowsze, obecne Safari) nie mają już tych problemów. (Niestety, w chwili pisania tego artykułu, IE8 pozostaje w powszechnym użyciu, a więc korzystanie z NFE z kodem dla sieci jest nadal problematyczne.)

Inicjator funkcji dostępu (ES5 +)

Czasami funkcje mogą wkradać się w dużej mierze niezauważone; tak jest w przypadku funkcji dostępu . Oto przykład:

 
var obj = {
    value: 0,
    get f() {
        return this.value;
    },
    set f(v) {
        this.value = v;
    }
};
console.log(obj.f);         // 0
console.log(typeof obj.f);  // "number"

Zauważ, że kiedy użyłem tej funkcji, nie użyłem ()! To dlatego, że jest to funkcja dostępu dla właściwości. Otrzymujemy i ustawiamy właściwość w normalny sposób, ale za kulisami funkcja jest wywoływana.

Możesz także utworzyć funkcje dostępu z Object.defineProperty, Object.defineProperties i mniej znanym drugim argumentem do Object.create.

Strzałka Wyrażenie funkcji (ES2015 +)

ES2015 przynosi nam funkcję strzałki . Oto jeden przykład:

 
var a = [1, 2, 3];
var b = a.map(n => n * 2);
console.log(b.join(", ")); // 2, 4, 6

Widzisz, że n => n * 2 ukrywa się w rozmowie map()? To jest funkcja.

Kilka rzeczy o funkcjach strzałek:

  1. Nie mają własnego this. Zamiast tego zamykają this kontekstu, w którym zostały zdefiniowane. (Zamykają również ponad arguments i, w stosownych przypadkach, super). Oznacza to, że this w nich jest taki sam jak this, gdzie są tworzone, i nie można ich zmienić.

  2. Jak zauważyłeś powyżej, nie używasz słowa kluczowego function; zamiast tego używasz =>.

Powyższy przykład n => n * 2 jest jedną z nich. Jeśli masz wiele argumentów do przekazania funkcji, używasz parens:

 
var a = [1, 2, 3];
var b = a.map((n, i) => n * i);
console.log(b.join(", ")); // 0, 2, 6

(Pamiętaj, że Array#map przekazuje wpis jako pierwszy argument, a indeks jako drugi.)

W obu przypadkach treść funkcji jest tylko wyrażeniem; wartość zwracana przez funkcję będzie automatycznie wynikiem tego wyrażenia (nie używasz jawnego return).

Jeśli robisz więcej niż jedno wyrażenie, użyj {} i jawnego return (jeśli chcesz zwrócić wartość), jak zwykle:

 
var a = [
  {first: "Joe", last: "Bloggs"},
  {first: "Albert", last: "Bloggs"},
  {first: "Mary", last: "Albright"}
];
a = a.sort((a, b) => {
  var rv = a.last.localeCompare(b.last);
  if (rv === 0) {
    rv = a.first.localeCompare(b.first);
  }
  return rv;
});
console.log(JSON.stringify(a));

Wersja bez { ... } jest nazywana funkcją strzałki z wyrażeniem lub zwięzłym ciałem . (Również: funkcja zwięzła .) Ta z { ... } definiująca ciało jest funkcją strzałki z ciałem funkcji . (Także: funkcja verbose .)

Deklaracja metody w inicjatorze obiektów (ES2015 +)

ES2015 umożliwia krótszą formę deklarowania właściwości, która odwołuje się do funkcji zwanej definicją metody ; wygląda to tak:

 
var o = {
    foo() {
    }
};

Prawie równoważny w ES5 i wcześniejszych będzie:

 
var o = {
    foo: function foo() {
    }
};

różnica (inna niż gadatliwość) polega na tym, że metoda może używać super, ale funkcja nie może. Na przykład, jeśli masz obiekt, który zdefiniował (powiedzmy) valueOf przy użyciu składni metody, może użyć super.valueOf(), aby uzyskać wartość Object.prototype.valueOf (zanim przypuszczalnie zrobisz coś z nią), podczas gdy wersja ES5 musiałaby zrobić Object.prototype.valueOf.call(this) zamiast tego.

Oznacza to również, że metoda ma odniesienie do obiektu, na którym została zdefiniowana, więc jeśli ten obiekt jest tymczasowy (na przykład przekazujesz go do Object.assign jako jeden z obiektów źródłowych), składnia metody mógłby oznaczać, że obiekt jest przechowywany w pamięci, w przeciwnym razie mógłby zostać usunięty (jeśli silnik JavaScript nie wykryje tej sytuacji i nie poradzi sobie z nią, jeśli żadna z metod nie używa super).

Deklaracje konstruktora i metody w class (ES2015 +)

ES2015 daje nam class składni, w tym zadeklarowanych konstruktorów i metod:

 
class Person {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName() {
        return this.firstName + " " + this.lastName;
    }
}

Istnieją dwie deklaracje funkcji powyżej: jedna dla konstruktora, która otrzymuje nazwę Person, a druga dla getFullName, która jest funkcją przypisaną do Person.prototype.

    
593
2019-01-11 13: 58: 57Z
  1. wtedy nazwa w jest po prostu ignorowana?
    2014-03-04 13: 37: 32Z
  2. @ PellePenna: Nazwy funkcji są przydatne dla wielu rzeczy. Moim zdaniem dwie wielkie rzeczy to rekursja, a nazwa funkcji wyświetlana jest w stosach wywołań, śladach wyjątków itp.
    2014-03-04 13: 42: 57Z
  3. @ ChaimEliyah - "Akceptacja nie oznacza, że ​​jest to najlepsza odpowiedź, oznacza to po prostu, że działała dla osoby, która zapytała." źródło
    2016-02-10 10: 19: 34Z
  4. @ A.R .: Całkiem prawdziwe. Zabawne jest jednak to, że powyżej „Najlepsze odpowiedzi pojawiają się najpierw, aby zawsze były łatwe do znalezienia”. Ponieważ zaakceptowana odpowiedź pojawia się najpierw nawet w przypadku odpowiedzi głosowanych wyżej, trasa może być nieco sprzeczna. ;-) Trochę niedokładne, jeśli określimy „najlepsze” głosami (co nie jest wiarygodne, to tylko to, co mamy), „najlepsze” odpowiedzi pojawiają się najpierw tylko wtedy, gdy używasz karty „Głosy” - w przeciwnym razie odpowiedzi, które są pierwsze, są aktywne lub najstarsze.
    2016-02-10 10: 32: 23Z
  5. @ T.J.Crowder: Agreed. „aranżacja według daty” jest czasami denerwująca.
    2016-02-10 10: 46: 56Z

Mówiąc o kontekście globalnym, zarówno instrukcja var, jak i FunctionDeclaration na końcu stworzą właściwość nieusuwalną w obiekcie globalnym, ale wartość obu może zostać zastąpiona .

Subtelna różnica między tymi dwoma sposobami polega na tym, że zmienna instancja proces jest uruchamiany (przed rzeczywistym wykonaniem kodu) wszystkie identyfikatory zadeklarowane przy użyciu var zostaną zainicjowane przy użyciu undefined, a te używane przez FunctionDeclaration będą dostępne od tego momentu, na przykład:

 
 alert(typeof foo); // 'function', it's already available
 alert(typeof bar); // 'undefined'
 function foo () {}
 var bar = function () {};
 alert(typeof bar); // 'function'

Przypisanie bar FunctionExpression odbywa się do czasu wykonania.

Globalna właściwość utworzona przez FunctionDeclaration może zostać nadpisana bez żadnych problemów, tak jak wartość zmiennej, np .:

 
 function test () {}
 test = null;

Inną oczywistą różnicą między twoimi dwoma przykładami jest to, że pierwsza funkcja nie ma nazwy, ale druga ma ją, co może być bardzo przydatne podczas debugowania (tj. sprawdzania stosu wywołań).

O twoim edytowanym pierwszym przykładzie (foo = function() { alert('hello!'); };), jest to niezadeklarowane zadanie, gorąco zachęcam cię, abyś zawsze używał słowa kluczowego var.

Przy przypisaniu, bez instrukcji var, jeśli przywoływany identyfikator nie zostanie znaleziony w łańcuchu zasięgu, stanie się właściwością usuwalną obiektu globalnego.

Również niezadeklarowane zadania rzucają ReferenceError na ECMAScript 5 w trybie ścisłym .

Musi przeczytać:

Uwaga : ta odpowiedź została scalona z inne pytanie , w którym główną wątpliwością i błędnym przekonaniem OP było to, że identyfikatory zadeklarowane przy pomocy FunctionDeclaration nie mogły zostać nadpisane, co nie jest prawdą.

    
138
2017-05-23 12: 10: 54Z
  1. Nie wiedziałem, że funkcje mogą zostać nadpisane w JavaScript! Również ten rozkaz analizowania jestduży punkt sprzedaży dla mnie. Myślę, że muszę oglądać, jak tworzę funkcje.
    2010-08-08 19: 43: 48Z
  2. + 0 do artykułu "Wyjaśnianie wyrażeń funkcji nazw" podczas jego 404ing. Możliwe lustro: kangax.github.com/nfe
    2011-11-29 15: 10: 16Z
  3. @ CMS Nice one. Pamiętaj jednak, że nigdy nie widziałem oryginału, więc nie wiem, czy to lustro, czy tylko inny artykuł o tym samym tytule!
    2011-11-29 15: 25: 01Z
  4. @ Mr_Chimp Jestem tego pewien, thewaybackmachine mówi, że ma 302 w czasie indeksowania, a przekierowanie dotyczyło podanego linku.
    2012-01-30 15: 18: 46Z

Dwa opublikowane przez Ciebie fragmenty kodu będą, dla prawie wszystkich celów, zachowywać się w ten sam sposób.

Jednak różnica w zachowaniu polega na tym, że w pierwszym wariancie (var functionOne = function() {}) tę funkcję można wywołać dopiero po tym punkcie kodu.

W drugim wariancie (function functionTwo()) funkcja jest dostępna dla kodu działającego powyżej miejsca, w którym funkcja jest zadeklarowana.

Dzieje się tak, ponieważ w pierwszym wariancie funkcja jest przypisana do zmiennej foo w czasie wykonywania. W drugim, funkcja jest przypisana do tego identyfikatora, foo, w czasie analizy.

Więcej informacji technicznych

JavaScript ma trzy sposoby definiowania funkcji.

  1. Twój pierwszy fragment pokazuje wyrażenie funkcji . Wymaga to użycia operatora „funkcja” w celu utworzenia funkcji - wynik tego operatora może być przechowywany w dowolnej właściwości zmiennej lub obiektu. Wyrażenie funkcji jest w ten sposób potężne. Wyrażenie funkcji jest często nazywane „funkcją anonimową”, ponieważ nie musi mieć nazwy,
  2. Twój drugi przykład to deklaracja funkcji . To używa instrukcji „function” do utworzenia funkcji. Funkcja jest udostępniana w czasie analizy i może być wywołana w dowolnym miejscu w tym zakresie. Nadal możesz przechowywać go w zmiennej lub właściwości obiektu.
  3. Trzeci sposób definiowania funkcji to konstruktor „Function ()” , który nie jest wyświetlany w oryginalnym poście. Nie zaleca się używania tego, ponieważ działa tak samo jak eval(), który ma swoje problemy.
118
2015-12-28 19: 47: 08Z

Lepsze wyjaśnienie odpowiedzi Grega

 
functionTwo();
function functionTwo() {
}

Dlaczego nie ma błędu? Zawsze uczono nas, że wyrażenia są wykonywane od góry do dołu (??)

Ponieważ:

  

Deklaracje funkcji i deklaracje zmiennych są zawsze przenoszone (hoisted) niewidocznie na górę ich zakresu zawierającego interpreter JavaScript. Parametry funkcji i nazwy zdefiniowane w języku są oczywiście już tam. ben cherry

Oznacza to, że kod taki jak ten:

 
functionOne();                  ---------------      var functionOne;
                                | is actually |      functionOne();
var functionOne = function(){   | interpreted |-->
};                              |    like     |      functionOne = function(){
                                ---------------      };

Zauważ, że część przypisania deklaracji nie została podniesiona. Tylko nazwa jest podnoszona.

Ale w przypadku deklaracji funkcji cała treść funkcji zostanie również podniesiona :

 
functionTwo();              ---------------      function functionTwo() {
                            | is actually |      };
function functionTwo() {    | interpreted |-->
}                           |    like     |      functionTwo();
                            ---------------
    
98
2017-05-23 12: 26: 42Z
  1. HI suhail dzięki za jasne informacje o temacie funkcji. Teraz moje pytanie brzmi, która będzie pierwszą deklaracją w hierarchii deklaracji, czy deklaracja zmiennej (functionOne) czy deklaracja funkcji (functionTwo)?
    2016-02-02 12: 09: 06Z

Inni komentatorzy już omówili semantyczną różnicę dwóch powyższych wariantów. Chciałem zwrócić uwagę na różnicę stylistyczną: tylko odmiana „przypisania” może ustawić właściwość innego obiektu.

Często tworzę moduły JavaScript ze wzorem takim jak ten:

 
(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

    exports.publicUtil = function() {
            ...
    };

    return exports;
})();

Z tym wzorem wszystkie funkcje publiczne będą używać przypisania, podczas gdy funkcje prywatne będą używać deklaracji.

(Zauważ, że przypisanie powinno wymagać średnika po wyrażeniu, podczas gdy deklaracja go zabrania.)

    
88
2014-10-19 22: 24: 30Z
  1. yuiblog. com /blog /2007/06/12 /module-pattern jest podstawową referencją dla wzorca modułu, o ile wiem. (Chociaż ten artykuł używa składni var foo = function(){...} nawet dla zmiennych prywatnych.
    2011-06-03 12: 32: 22Z
  2. To nie jest do końca prawda w niektórych starszych wersjach IE. (function window.onload() {} było czymś.)
    2013-04-21 19: 42: 51Z

Ilustracja tego, kiedy preferować pierwszą metodę od drugiej, polega na tym, że należy unikać nadpisywania poprzednich definicji funkcji.

Z

 
if (condition){
    function myfunction(){
        // Some code
    }
}

, ta definicja myfunction zastąpi poprzednią definicję, ponieważ zostanie wykonana w czasie analizy.

Podczas

 
if (condition){
    var myfunction = function (){
        // Some code
    }
}

wykonuje poprawną pracę, definiując myfunction tylko wtedy, gdy condition jest spełniony.

    
75
2017-06-29 14: 08: 06Z
  1. ten przykład jest dobry i jest bliski perfekcji, ale można go poprawić. lepszym przykładem byłoby zdefiniowanie var myFunc = null; poza pętlą lub poza blokiem if /elseif /else. Następnie możesz warunkowo przypisać różne funkcje do tej samej zmiennej. W JS lepszą konwencją jest przypisanie brakującej wartości do null, a następnie do undefined. Dlatego powinieneś zadeklarować myFunction jako null, a następnie przypisać go później warunkowo.
    2015-05-26 20: 31: 32Z

Ważnym powodem jest dodanie jednej i tylko jednej zmiennej jako „Root” przestrzeni nazw ...

 
var MyNamespace = {}
MyNamespace.foo= function() {

}

lub

 
var MyNamespace = {
  foo: function() {
  },
  ...
}

Istnieje wiele technik tworzenia nazw. Stało się to ważniejsze dzięki mnogości dostępnych modułów JavaScript.

Zobacz także Jak zadeklarować przestrzeń nazw w JavaScript?

    
60
2017-05-23 11: 55: 19Z
  1. Wygląda na to, że ta odpowiedź została połączona z tym pytaniem z innego pytania, a sformułowanie może wydawać się trochę niezwiązane z to pytanie. Czy rozważyłbyś edycję odpowiedzi, aby była bardziej ukierunkowana na to pytanie? (powtarzam: to wcale nie jest twoja wina ... tylko efekt uboczny połączonego pytania). Możesz go również usunąć i myślę, że zachowasz swoją reputację. Albo możesz to zostawić; ponieważ jest stary, może nie mieć większego znaczenia.
    2013-05-29 21: 13: 50Z

Podnoszenie to akcja interpretera JavaScript polegająca na przenoszeniu wszystkich deklaracji zmiennych i funkcji na szczyt bieżącego zakresu.

Jednak tylko rzeczywiste deklaracje są podnoszone. zostawiając zadania tam, gdzie są.

  • zmiennae's /Function zadeklarowane wewnątrz strony mają globalny dostęp do dowolnego miejsca na tej stronie.
  • zmienna /Funkcje zadeklarowane wewnątrz funkcji mają zasięg lokalny. oznacza, że ​​są dostępne /dostępne w treści funkcji (zakres), nie są dostępne poza ciałem funkcji.

Zmienna

Javascript nazywa się językiem luźno wpisanym. Co oznacza, że ​​zmienne JavaScript mogą zawierać wartość dowolnego Typu danych . Javascript automatycznie zajmuje się zmianą typu zmiennej na podstawie wartości /literału podanego w czasie wykonywania.

 
global_Page = 10;                                               var global_Page;      « undefined
    « Integer literal, Number Type.   -------------------       global_Page = 10;     « Number         
global_Page = 'Yash';                 |   Interpreted   |       global_Page = 'Yash'; « String
    « String literal, String Type.    «       AS        «       global_Page = true;   « Boolean 
var global_Page = true;               |                 |       global_Page = function (){          « function
    « Boolean Type                    -------------------                 var local_functionblock;  « undefined
global_Page = function (){                                                local_functionblock = 777;« Number
    var local_functionblock = 777;                              };  
    // Assigning function as a data.
};  

Funkcja

 
function Identifier_opt ( FormalParameterList_opt ) { 
      FunctionBody | sequence of statements

      « return;  Default undefined
      « return 'some data';
}
  • funkcje zadeklarowane wewnątrz strony są podnoszone na górę strony mającej globalny dostęp.
  • funkcje zadeklarowane wewnątrz bloku funkcyjnego są podnoszone na górę bloku.
  • Domyślną wartością zwracaną przez funkcję jest „ undefined ', Zmienna deklaracja domyślna wartość także „niezdefiniowana”

     
    Scope with respect to function-block global. 
    Scope with respect to page undefined | not available.
    

Deklaracja funkcji

 
function globalAccess() {                                  function globalAccess() {      
}                                  -------------------     }
globalAccess();                    |                 |     function globalAccess() { « Re-Defined / overridden.
localAccess();                     «   Hoisted  As   «         function localAccess() {
function globalAccess() {          |                 |         }
     localAccess();                -------------------         localAccess(); « function accessed with in globalAccess() only.
     function localAccess() {                              }
     }                                                     globalAccess();
}                                                          localAccess(); « ReferenceError as the function is not defined

Wyrażenie funkcji

 
        10;                 « literal
       (10);                « Expression                (10).toString() -> '10'
var a;                      
    a = 10;                 « Expression var              a.toString()  -> '10'
(function invoke() {        « Expression Function
 console.log('Self Invoking');                      (function () {
});                                                               }) () -> 'Self Invoking'

var f; 
    f = function (){        « Expression var Function
    console.log('var Function');                                   f ()  -> 'var Function'
    };

Funkcja przypisana do zmiennej Przykład:

 
(function selfExecuting(){
    console.log('IIFE - Immediately-Invoked Function Expression');
}());

var anonymous = function (){
    console.log('anonymous function Expression');
};

var namedExpression = function for_InternalUSE(fact){
    if(fact === 1){
        return 1;
    }

    var localExpression = function(){
        console.log('Local to the parent Function Scope');
    };
    globalExpression = function(){ 
        console.log('creates a new global variable, then assigned this function.');
    };

    //return; //undefined.
    return fact * for_InternalUSE( fact - 1);   
};

namedExpression();
globalExpression();

javascript interpretowany jako

 
var anonymous;
var namedExpression;
var globalExpression;

anonymous = function (){
    console.log('anonymous function Expression');
};

namedExpression = function for_InternalUSE(fact){
    var localExpression;

    if(fact === 1){
        return 1;
    }
    localExpression = function(){
        console.log('Local to the parent Function Scope');
    };
    globalExpression = function(){ 
        console.log('creates a new global variable, then assigned this function.');
    };

    return fact * for_InternalUSE( fact - 1);    // DEFAULT UNDEFINED.
};

namedExpression(10);
globalExpression();

Możesz sprawdzić deklarację funkcji, test wyrażeń w różnych przeglądarkach używając jsperf Test Runner


Klasy funkcji konstruktora ES5 : Obiekty funkcyjne utworzone przy użyciu Function.prototype.bind

Traktuje JavaScript jako obiekty pierwszej klasy, więc będąc obiektem, możesz przypisać właściwości do funkcji.

 
function Shape(id) { // Function Declaration
    this.id = id;
};
    // Adding a prototyped method to a function.
    Shape.prototype.getID = function () {
        return this.id;
    };
    Shape.prototype.setID = function ( id ) {
        this.id = id;
    };

var expFn = Shape; // Function Expression

var funObj = new Shape( ); // Function Object
funObj.hasOwnProperty('prototype'); // false
funObj.setID( 10 );
console.log( funObj.getID() ); // 10

ES6 wprowadził funkcję strzałek : wyrażenie funkcji strzałki ma krótszą składnię, najlepiej nadaje się do funkcji innych niż metody i nie można ich używać jako konstruktorów.

  

53

2017-09-28 06: 35: 18Z
  1. ahm, twoja odpowiedź ... czy to nie jest niejednoznaczne? dobrze napisane, ale tak +1 za wydawanie i pisanie zbyt wielu informacji.
    2016-01-31 17: 56: 52Z

Dodaję własną odpowiedź tylko dlatego, że wszyscy dokładnie zakryli część podnośnika.

Zastanawiałem się, która droga jest już od dłuższego czasu i dzięki http://jsperf.com teraz wiem :)

wprowadź opis obrazu tutaj>> </p>

<p> <strong> Deklaracje funkcji </strong> są szybsze, a to, co naprawdę ma znaczenie w web dev? ;) </p>
    </div>
<div class = 38

2015-05-01 15: 06: 55Z
  1. Powiedziałbym, że łatwość konserwacji jest najważniejszym aspektem większości kodu. Wydajność jest ważna, ale w większości przypadków IO może być większym wąskim gardłem, niż sposób definiowania funkcji. Istnieją jednak pewne problemy, w których potrzebujesz każdej wydajności, którą możesz uzyskać, i jest to przydatne w takich przypadkach. Dobrze też mieć tutaj odpowiedź, która jasno odpowiada na dobrze zdefiniowaną część pytania.
    2015-05-02 15: 22: 58Z
  2. Cóż, odkryłem, że jest inaczej w Firefoksie. jsperf.com/sandytest
    2015-11-17 14: 15: 48Z
  3. Microbenchmarks zawsze zawodzą. Patrząc na jsperf.com to marnowanie czasu. Naprawdę potrzebujesz spojrzeć na kod źródłowy silnika JS, oficjalną dokumentację lub przynajmniej wąchać blogi dev lub listy mailingowe.
    2016-01-10 15: 13: 21Z
  4. Tylko aktualizacja, ponieważ teraz przeszedłem w pełni funkcjonalny styl programowania w JavaScript, nigdy nie używam deklaracji, tylko wyrażenia funkcji, dzięki czemu mogę łączyć i wywoływać moje funkcje przez ich nazwy zmiennych. Sprawdź RamdaJS ...
    2016-12-28 16: 56: 35Z
  5. @ SandeepNayak Po prostu uruchomiłem własny test w Firefoksie 50.0.0 /Windows 7 0.0.0, a tak naprawdę jest on taki sam jak w przypadku Leona. Jeśli więc twój test jest poprawny, dochodzę do wniosku, że testy jsperf nie są wskazówkami i wszystko zależy od twojej przeglądarki i /lub wersji systemu operacyjnego lub konkretnego stanu bieżącej maszyny w danym momencie.
    2017-01-10 13: 40: 22Z

Deklaracja funkcji i wyrażenie funkcji przypisane do zmiennej zachowują się tak samo po ustanowieniu wiązania.

Istnieje jednak różnica w jak i kiedy obiekt funkcji jest faktycznie powiązany z jego zmienną. Ta różnica wynika z mechanizmu zwanego zmienną podnoszącą w JavaScript.

Zasadniczo wszystkie deklaracje funkcji i deklaracje zmiennych są podnoszone na szczyt funkcji , w której występuje deklaracja (dlatego mówimy, że JavaScript ma zakres funkcji ) .

  • Gdy deklaracja funkcji jest podnoszona, treść funkcji „podąża” więc gdy ciało funkcji jest oceniane, zmienna natychmiast być związanym z obiektem funkcji.

  • Gdy podnoszona jest deklaracja zmiennej, inicjalizacja nie śledzić, ale jest „pozostawiony”. Zmienna jest inicjowana na  undefined na początku treści funkcji i będzie przypisany wartość w oryginalnej lokalizacji w kodzie. (W rzeczywistości zostanie przypisana wartość w każdej lokalizacji, w której występuje deklaracja zmiennej o tej samej nazwie.)

Kolejność podnoszenia jest również ważna: deklaracje funkcji mają pierwszeństwo przed deklaracjami zmiennych o tej samej nazwie, a ostatnia deklaracja funkcji ma pierwszeństwo przed poprzednimi deklaracjami funkcji o tej samej nazwie.

Niektóre przykłady ...

 
var foo = 1;
function bar() {
  if (!foo) {
    var foo = 10 }
  return foo; }
bar() // 10

Zmienna foo jest podnoszona na górę funkcji, zainicjowana na undefined, tak że !foo wynosi true, więc foo ma 10. foo poza zasięgiem bar nie odgrywa żadnej roli i jest nietknięty.

 
function f() {
  return a; 
  function a() {return 1}; 
  var a = 4;
  function a() {return 2}}
f()() // 2

function f() {
  return a;
  var a = 4;
  function a() {return 1};
  function a() {return 2}}
f()() // 2

Deklaracje funkcji mają pierwszeństwo przed deklaracjami zmiennych, a ostatnia deklaracja funkcji „trzyma się”.

 
function f() {
  var a = 4;
  function a() {return 1}; 
  function a() {return 2}; 
  return a; }
f() // 4

W tym przykładzie a jest inicjowany przez obiekt funkcji wynikający z oceny deklaracji drugiej funkcji, a następnie przypisywany jest 4.

 
var a = 1;
function b() {
  a = 10;
  return;
  function a() {}}
b();
a // 1

Tutaj deklaracja funkcji jest podnoszona jako pierwsza, deklarując i inicjalizując zmienną a. Następnie tej zmiennej przypisuje się 10. Innymi słowy: przypisanie nie przypisuje się do zmiennej zewnętrznej a.

    
32
2013-02-06 16: 29: 20Z
  1. Masz trochę dziwny sposób na umieszczenie zamykających nawiasów klamrowych. Czy jesteś koderem Pythona? Wygląda na to, że próbujesz wyglądać jak JavaScript w Pythonie. Obawiam się, że jest to mylące dla innych ludzi. Gdybym musiał utrzymać kod JavaScript, najpierw pozwoliłbym twojemu kodowi przejść przez automatyczną ładną drukarkę.
    2013-05-14 12: 46: 50Z
  2. Doskonały post. „Funkcja samowykonująca się” lub „natychmiast wywołane wyrażenie funkcji” powinna być wystarczająco łatwa do zobaczenia, a jego preferencje stylu nie powinny umniejszać jego pozycji - co jest dokładne i doskonale podsumowuje „podnoszenie”. +1
    2013-12-17 18: 13: 19Z

Pierwszy przykład to deklaracja funkcji:

 
function abc(){}

Drugi przykład to zabawawyrażenie ction:

 
var abc = function() {};

Główna różnica polega na tym, jak są podnoszone (podnoszone i deklarowane). W pierwszym przykładzie podnoszona jest cała deklaracja funkcji. W drugim przykładzie podnoszona jest tylko zmienna „abc”, jej wartość (funkcja) będzie niezdefiniowana, a sama funkcja pozostanie w miejscu, w którym została zadeklarowana.

Mówiąc prosto:

 
//this will work
abc(param);
function abc(){}

//this would fail
abc(param);
var abc = function() {}

Aby dowiedzieć się więcej na ten temat, zdecydowanie to polecam link

    
31
2015-05-09 09: 37: 41Z
  1. Twój przykład jest taki sam jak najlepsza odpowiedź
    2014-06-05 08: 34: 58Z
  2. Głównym powodem opublikowania tej odpowiedzi było podanie linku na dole. To był kawałek, którego mi brakowało, aby w pełni zrozumieć powyższe pytanie.
    2014-06-08 05: 44: 23Z
  3. To bardzo fajne, że chciałeś udostępnić link. Ale linki do dodatkowych informacji w SO powinny być tylko komentarzem do pytania lub ulubionej odpowiedzi. Bardzo nieoptymalne jest zaśmiecanie długiej, skomplikowanej strony taką powtarzającą się informacją, aby dodać pojedynczy użyteczny link na końcu. Nie, nie dostaniesz punktów rep za udostępnienie linku, ale będziesz pomagać społeczności.
    2015-01-13 00: 26: 03Z

Jeśli chodzi o koszt utrzymania kodu, nazwane funkcje są bardziej preferowane:

  • Niezależne od miejsca, w którym zostały zadeklarowane (ale nadal ograniczone zakresem).
  • Bardziej odporny na błędy, takie jak inicjalizacja warunkowa (nadal możesz przesłonić, jeśli chcesz).
  • Kod staje się bardziej czytelny, alokując funkcje lokalne oddzielnie dla funkcji zakresu. Zazwyczaj w zakresie, w którym funkcjonuje, najpierw następuje deklaracja lokalnych funkcji.
  • W debuggerze wyraźnie zobaczysz nazwę funkcji na stosie wywołań zamiast funkcji „anonimowo /oceniane”.

Podejrzewam, że następują kolejne PROS dla nazwanych funkcji. A to, co jest wymienione jako zaleta nazwanych funkcji, jest wadą dla anonimowych.

Historycznie, anonimowe funkcje wynikały z niezdolności JavaScript jako języka do wymieniania członków o nazwanych funkcjach:

 
{
    member:function() { /* How do I make "this.member" a named function? */
    }
}
    
28
2015-12-28 19: 44: 15Z
  1. Istnieje test do potwierdzenia: blog.firsov.net/2010/01/… Test wydajności JS - zakres i nazwane funkcje - Analytics
    2010-02-04 00: 45: 03Z

Używam podejścia zmiennego w moim kodzie z bardzo konkretnego powodu, którego teoria została omówiona w sposób abstrakcyjny powyżej, ale przykład może pomóc niektórym ludziom jak ja, z ograniczoną wiedzą na temat JavaScript.

Mam kod, który muszę uruchomić z 160 niezależnie zaprojektowanymi markami. Większość kodu znajduje się w udostępnionych plikach, ale elementy specyficzne dla marki są w osobnym pliku, po jednym dla każdego brandingu.

Niektóre marki wymagają określonych funkcji, a niektóre nie. Czasami muszę dodawać nowe funkcje, aby robić nowe rzeczy związane z brandingiem. Cieszę się, że mogę zmienić wspólne kodowanie, ale nie chcę zmieniać wszystkich 160 zestawów plików brandingu.

Używając składni zmiennej, mogę zadeklarować zmienną (zasadniczo wskaźnik funkcji) we współdzielonym kodzie i przypisać trywialną funkcję kodu pośredniego lub ustawić ją na wartość null.

Jedna lub dwie marki, które wymagają konkretnej implementacji funkcji, mogą następnie zdefiniować swoją wersję funkcji i przypisać ją do zmiennej, jeśli chcą, a reszta nic nie robi. Mogę przetestować pustą funkcję befoPonownie wykonam go we współdzielonym kodzie.

Z powyższych komentarzy ludzi wynika, że ​​możliwe jest również ponowne zdefiniowanie funkcji statycznej, ale myślę, że zmienne rozwiązanie jest ładne i jasne.

    
24
2015-12-28 20: 26: 41Z

W kategoriach informatyki mówimy o funkcjach anonimowych i nazwanych funkcjach. Myślę, że najważniejszą różnicą jest to, że funkcja anonimowa nie jest związana z nazwą, stąd nazwa funkcja anonimowa. W JavaScript jest to obiekt pierwszej klasy dynamicznie deklarowany w czasie wykonywania.

Aby uzyskać więcej informacji na temat funkcji anonimowych i rachunku lambda, Wikipedia jest dobrym początkiem ( http: //en. wikipedia.org/wiki/Anonymous_function ).

    
22
2014-10-19 22: 25: 19Z

Odpowiedź Grega jest wystarczająco dobra, ale nadal chciałbym dodać coś, czego nauczyłem się właśnie oglądając filmy Douglasa Crockforda .

Wyrażenie funkcji:

 
var foo = function foo() {};

Instrukcja funkcji:

 
function foo() {};

Instrukcja funkcji jest tylko skrótem dla instrukcji var o wartości function.

Więc

 
function foo() {};

rozwija się do

 
var foo = function foo() {};

Który rozszerza się dalej:

 
var foo = undefined;
foo = function foo() {};

I obie są podnoszone na górę kodu.

Zrzut ekranu z filmu

    
22
2017-05-23 12: 18: 36Z
  1. Przepraszamy, ale to jest niepoprawne - nie wiem, co Crockford próbuje powiedzieć na tym slajdzie. Zarówno funkcja jak i deklaracje zmiennych są zawsze podnoszone do góry zakresu. Różnica polega na tym, że przypisania zmiennych (niezależnie od tego, czy przypisujesz je ciągiem znaków, boolean czy funkcja) nie są podnoszone na górę, podczas gdy ciała funkcji (za pomocą deklaracji funkcji) są.
    2015-10-05 16: 25: 35Z
  2. 2015-10-05 16: 51: 24Z

@EugeneLazutkin daje przykład, gdzie on nazywa przypisaną funkcję, aby móc używać shortcut() jako wewnętrznego odniesienia do siebie. John Resig podaje inny przykład - kopiowanie funkcji rekurencyjnej przypisanej do innego obiektu w jego Nauka zaawansowanego Javascript samouczek. Podczas gdy przypisywanie funkcji do właściwości nie jest tutaj ściśle kwestią, polecam aktywnie wypróbować samouczek - uruchom kod, klikając przycisk w prawym górnym rogu i kliknij dwukrotnie kod, który chcesz edytować według własnych upodobań.

Przykłady z samouczka: wywołania rekurencyjne w yell():

Testy nie powiodą się, gdy oryginalny obiekt ninja zostanie usunięty. (strona 13)

 
var ninja = { 
  yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." ); 

var samurai = { yell: ninja.yell }; 
var ninja = null; 

try { 
  samurai.yell(4); 
} catch(e){ 
  assert( false, "Uh, this isn't good! Where'd ninja.yell go?" ); 
}

Jeśli nazwiesz funkcję, która będzie wywoływana rekurencyjnie, testy zostaną zakończone. (strona 14)

 
var ninja = { 
  yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" ); 

var samurai = { yell: ninja.yell }; 
var ninja = {}; 
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );
    
18
2017-05-23 12: 34: 59Z
  1. Tylko zadzwonienie do this.yell też działa :)
    2013-04-21 20: 54: 08Z

Inną różnicą, która nie jest wymieniona w innych odpowiedziach, jest to, że jeśli używasz funkcji anonimowej

 
var functionOne = function() {
    // Some code
};

i używaj tego jako konstruktora jak w

 
var one = new functionOne();

wtedy one.constructor.name nie zostanie zdefiniowany. Function.name jest niestandardowy, ale jest obsługiwany przez Firefox, Chrome, inne przeglądarki oparte na Webkit i IE 9+.

Z

 
function functionTwo() {
    // Some code
}
two = new functionTwo();

możliwe jest pobranie nazwy konstruktora jako ciągu z two.constructor.name.

    
16
2013-01-17 08: 48: 42Z
  1. Nazwa w pierwszym przypadku nie zostanie zdefiniowana, ponieważ jest to funkcja anonimowa przypisana do zmiennej. Myślę, że słowo anonimowe zostało wymyślone dla rzeczy, które nie mają zdefiniowanej nazwy :)
    2013-01-17 06: 13: 39Z
  2. W tym przykładzie dwa = nowe stają się funkcją globalną, ponieważ nie ma var
    2015-08-29 05: 04: 03Z

Jeśli użyjesz tych funkcji do tworzenia obiektów, otrzymasz:

 
var objectOne = new functionOne();
console.log(objectOne.__proto__); // prints "Object {}" because constructor is an anonymous function

var objectTwo = new functionTwo();
console.log(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function
    
14
2013-10-25 16: 38: 22Z
  1. Nie mogę tego odtworzyć. console.log(objectOne.__proto__); drukuje „functionOne {}” w mojej konsoli. Jakieś pomysły, dlaczego tak może być?
    2015-03-22 10: 06: 25Z
  2. Nie mogę go również odtworzyć.
    2016-01-21 15: 57: 23Z
  3. To jest możliwość twojego debuggera (aby wyświetlić "klasę" zalogowanego obiektu), a większość z nich jest w stanie wyprowadzić nazwę nawet dla anonimowych wyrażeń funkcji, które dni. Powinieneś wyjaśnić, że nie ma żadnej funkcjonalnej różnicy między dwoma instancjami.
    2016-01-21 16: 26: 32Z

Pierwszy (funkcja doSomething (x)) powinien być częścią zapisu obiektu.

Drugi (var doSomething = function(x){ alert(x);}) po prostu tworzy funkcję anonimową i przypisuje ją do zmiennej, doSomething. Więc doSomething () wywoła funkcję.

Możesz wiedzieć, czym jest deklaracja funkcji i wyrażenie funkcji .

Deklaracja funkcji definiuje zmienną o nazwie funkcji bez konieczności przypisywania zmiennych. Deklaracje funkcji występują jako samodzielne konstrukcje i nie można ich zagnieżdżać w blokach niefunkcjonalnych.

 
function foo() {
    return 3;
}
  

ECMA 5 (13.0) definiuje składnię jako
  Identyfikator funkcji (FormalParameterList opt ) {BodyBody}

W powyższym warunku nazwa funkcji jest widoczna w zakresie i zakresie jej rodzica (w przeciwnym razie byłaby nieosiągalna).

I w wyrażeniu funkcji

Wyrażenie funkcji definiuje funkcję jako część większej składni wyrażenia (zazwyczaj przypisanie zmiennej). Funkcje zdefiniowane za pomocą wyrażeń funkcji mogą być nazwane lub anonimowe. Wyrażenia funkcji nie powinny zaczynać się od „funkcji”.

 
// Anonymous function expression
var a = function() {
    return 3;
}

// Named function expression
var a = function foo() {
    return 3;
}

// Self-invoking function expression
(function foo() {
    alert("hello!");
})();
  

ECMA 5 (13.0) definiuje składnię jako
  identyfikator funkcji opt (FormalParameterList opt ) {FunctionBody}

    
14
2015-12-28 20: 29: 40Z

Wymieniam poniższe różnice:

  1. Deklaracja funkcji może być umieszczona w dowolnym miejscu kodu. Nawet jeśli jestpobudzony przed pojawieniem się definicji w kodzie, zostaje wykonany, ponieważ deklaracja funkcji jest przypisana do pamięci lub w taki sposób, w jaki jest podnoszona, zanim jakikolwiek inny kod na stronie zacznie działać.

    Spójrz na poniższą funkcję:

     
    function outerFunction() {
        function foo() {
           return 1;
        }
        return foo();
        function foo() {
           return 2;
        }
    }
    alert(outerFunction()); // Displays 2
    

    Dzieje się tak, ponieważ podczas wykonywania wygląda tak: -

     
    function foo() {  // The first function declaration is moved to top
        return 1;
    }
    function foo() {  // The second function declaration is moved to top
        return 2;
    }
    function outerFunction() {
        return foo();
    }
    alert(outerFunction()); //So executing from top to bottom,
                            //the last foo() returns 2 which gets displayed
    

    Wyrażenie funkcji, jeśli nie zostanie zdefiniowane przed wywołaniem, spowoduje błąd. Również tutaj sama definicja funkcji nie jest przenoszona na górę ani zapisywana w pamięci, jak w deklaracjach funkcji. Ale zmienna, do której przypisujemy funkcję, zostaje podniesiona i przypisany do niej jest niezdefiniowany .

    Ta sama funkcja przy użyciu wyrażeń funkcji:

     
    function outerFunction() {
        var foo = function() {
           return 1;
        }
        return foo();
        var foo = function() {
           return 2;
        }
    }
    alert(outerFunction()); // Displays 1
    

    Dzieje się tak, ponieważ podczas wykonywania wygląda tak:

     
    function outerFunction() {
       var foo = undefined;
       var foo = undefined;
    
       foo = function() {
          return 1;
       };
       return foo ();
       foo = function() {   // This function expression is not reachable
          return 2;
       };
    }
    alert(outerFunction()); // Displays 1
    
  2. Nie jest bezpieczne pisanie deklaracji funkcji w blokach niefunkcjonalnych, takich jak , jeśli , ponieważ nie będą dostępne.

     
    if (test) {
        function x() { doSomething(); }
    }
    
  3. Nazwane wyrażenie funkcji, takie jak poniższe, może nie działać w przeglądarkach Internet Explorer wcześniejszych niż 9.

     
    var today = function today() {return new Date()}
    
14
2015-12-28 20: 35: 28Z
  1. @ Arjun Jaki jest problem, jeśli pytanie zostało zadane wiele lat wcześniej? Odpowiedź nie tylko przynosi korzyści OP, ale potencjalnie wszystkim użytkownikom SO, niezależnie od tego, kiedy pytanie zostało zadane. A co jest nie tak z odpowiadaniem na pytania, które już mają zaakceptowaną odpowiedź?
    2015-10-05 12: 58: 33Z
  2. @ Arjun musisz zrozumieć odpowiedź na stare pytania nie jest zła. Gdyby tak było, SO miałoby taką barierę. Wyobraź sobie, że nastąpiła zmiana API (choć nie w kontekście tego pytania) i ktoś ją zauważy i dostarczy odpowiedź nowym API, czy nie powinno to być dozwolone? Dopóki odpowiedź nie ma sensu i nie ma tu miejsca, zostanie automatycznie usunięta i usunięta. Nie musisz się tym przejmować !!!!
    2015-10-18 21: 37: 08Z

W świetle argumentu „nazwane funkcje wyświetlane w śledzeniu stosu” nowoczesne silniki JavaScript są w rzeczywistości całkiem zdolne do reprezentowania anonimowych funkcji.

W tym piśmie V8, SpiderMonkey, Chakra i Nitro zawsze odnoszą się do nazwanych funkcji według ich nazw. Prawie zawsze odnoszą się do anonimowej funkcji przez jej identyfikator, jeśli taki ma.

SpiderMonkey może wymyślić nazwę anonimowej funkcji zwróconej z innej funkcji. Reszta nie może.

Jeśli naprawdę chciałbyś, aby wywołania zwrotne iteratora i powodzenia pojawiały się w śladzie, możesz nazwać je również ...

 
[].forEach(function iterator() {});

Ale w większości nie jest to warte podkreślenia.

Uprząż ( Fiddle )

 
'use strict';

var a = function () {
    throw new Error();
},
    b = function b() {
        throw new Error();
    },
    c = function d() {
        throw new Error();
    },
    e = {
        f: a,
        g: b,
        h: c,
        i: function () {
            throw new Error();
        },
        j: function j() {
            throw new Error();
        },
        k: function l() {
            throw new Error();
        }
    },
    m = (function () {
        return function () {
            throw new Error();
        };
    }()),
    n = (function () {
        return function n() {
            throw new Error();
        };
    }()),
    o = (function () {
        return function p() {
            throw new Error();
        };
    }());

console.log([a, b, c].concat(Object.keys(e).reduce(function (values, key) {
    return values.concat(e[key]);
}, [])).concat([m, n, o]).reduce(function (logs, func) {

    try {
        func();
    } catch (error) {
        return logs.concat('func.name: ' + func.name + '\n' +
                           'Trace:\n' +
                           error.stack);
        // Need to manually log the error object in Nitro.
    }

}, []).join('\n\n'));

V8

 
func.name: 
Trace:
Error
    at a (http://localhost:8000/test.js:4:11)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: b
Trace:
Error
    at b (http://localhost:8000/test.js:7:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: d
Trace:
Error
    at d (http://localhost:8000/test.js:10:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at a (http://localhost:8000/test.js:4:11)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: b
Trace:
Error
    at b (http://localhost:8000/test.js:7:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: d
Trace:
Error
    at d (http://localhost:8000/test.js:10:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at e.i (http://localhost:8000/test.js:17:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: j
Trace:
Error
    at j (http://localhost:8000/test.js:20:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: l
Trace:
Error
    at l (http://localhost:8000/test.js:23:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at http://localhost:8000/test.js:28:19
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: n
Trace:
Error
    at n (http://localhost:8000/test.js:33:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: p
Trace:
Error
    at p (http://localhost:8000/test.js:38:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27 test.js:42

SpiderMonkey

 
func.name: 
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
e.i@http://localhost:8000/test.js:17:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: j
Trace:
j@http://localhost:8000/test.js:20:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: l
Trace:
l@http://localhost:8000/test.js:23:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
m</<@http://localhost:8000/test.js:28:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: n
Trace:
n@http://localhost:8000/test.js:33:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: p
Trace:
p@http://localhost:8000/test.js:38:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1

Czakra

 
func.name: undefined
Trace:
Error
   at a (http://localhost:8000/test.js:4:5)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at b (http://localhost:8000/test.js:7:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at d (http://localhost:8000/test.js:10:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at a (http://localhost:8000/test.js:4:5)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at b (http://localhost:8000/test.js:7:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at d (http://localhost:8000/test.js:10:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at e.i (http://localhost:8000/test.js:17:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at j (http://localhost:8000/test.js:20:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at l (http://localhost:8000/test.js:23:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at Anonymous function (http://localhost:8000/test.js:28:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at n (http://localhost:8000/test.js:33:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at p (http://localhost:8000/test.js:38:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)

Nitro

 
func.name: 
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
i@http://localhost:8000/test.js:17:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: j
Trace:
j@http://localhost:8000/test.js:20:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: l
Trace:
l@http://localhost:8000/test.js:23:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
http://localhost:8000/test.js:28:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: n
Trace:
n@http://localhost:8000/test.js:33:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: p
Trace:
p@http://localhost:8000/test.js:38:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
    
11
2015-01-13 03: 24: 58Z

Istnieją cztery godne uwagi porównania między dwiema różnymi deklaracjami funkcji, które wymieniono poniżej.

  1. Dostępność (zakres) funkcji

Poniższe działa, ponieważ function add() ma zasięg do najbliższego bloku:

 
try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

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

Poniższe nie działa (ponieważ var add= zastępuje function add()).

 
try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

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

Poniższe nie działa, ponieważ add jest zadeklarowane po użyciu.

 
try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

var add=function(a, b){
  return a + b;
}
  1. (funkcja) .name

Nazwa funkcji function thefuncname(){} to nazwa_funkcji , gdy zostanie zadeklarowana w ten sposób.

 
function foobar(a, b){}

console.log(foobar.name);

 
var a = function foobar(){};

console.log(a.name);

W przeciwnym razie, jeśli function jest deklarowane jako function(){}, funkcja .name jest pierwszą zmienną używaną do przechowywania funkcji.

 
var a = function(){};
var b = (function(){ return function(){} });

console.log(a.name);
console.log(b.name);

Jeśli dla funkcji nie ustawiono żadnych zmiennych, nazwa funkcji jest pustym łańcuchem ("").

 
console.log((function(){}).name === "");

Wreszcie, chociaż zmienna, do której funkcja jest przypisana, początkowo ustawia nazwę, kolejne zmienne ustawione dla tej funkcji nie zmieniają nazwy.

 
var a = function(){};
var b = a;
var c = b;

console.log(a.name);
console.log(b.name);
console.log(c.name);
  1. Wydajność

W Google V8 i Firefox Spidermonkey może występować kilka różnic mikrosekund JIST, ale ostatecznie wynik jest taki sam. Aby to udowodnić, przyjrzyjmy się skuteczności JSPerf przy mikrobenchmarkach, porównując prędkość dwóch pustych fragmentów kodu. Testy JSPerf można znaleźć tutaj . I testy jsben.ch znajdują się tutaj . Jak widać, istnieje wyraźna różnica, gdy nie powinno być żadnej. Jeśli naprawdę jesteś fanatykiem wydajności takim jak ja, to może warto być bardziej przy próbie zmniejszenia liczby zmiennych i funkcji w zakresie, a zwłaszcza eliminacji polimorfizmu (np. Przy użyciu tej samej zmiennej do przechowywania dwóch różnych typów). p>

  1. Zmienna zmienność

Gdy użyjesz słowa kluczowego var do zadeklarowania zmiennej, możesz ponownie przypisać inną wartość do zmiennej w ten sposób.

 
(function(){
    "use strict";
    var foobar = function(){}; // initial value
    try {
        foobar = "Hello World!"; // new value
        console.log("[no error]");
    } catch(error) {
        console.log("ERROR: " + error.message);
    }
    console.log(foobar, window.foobar);
})();

Jednak, gdy używamy instrukcji const, zmienna odniesienia staje się niezmienna. Oznacza to, że nie możemy przypisać nowej wartości do zmiennej. Należy jednak pamiętać, że nie powoduje to, że zawartość zmiennej jest niezmienna: jeśli zrobisz const arr = [], nadal możesz zrobić arr[10] = "example". Tylko wykonanie czegoś takiego jak arr = "new value" lub arr = [] spowodowałoby błąd, jak pokazano poniżej.

 
(function(){
    "use strict";
    const foobar = function(){}; // initial value
    try {
        foobar = "Hello World!"; // new value
        console.log("[no error]");
    } catch(error) {
        console.log("ERROR: " + error.message);
    }
    console.log(foobar, window.foobar);
})();

Co ciekawe, jeśli zadeklarujemy zmienną jako function funcName(){}, to niezmienność zmiennej jest taka sama, jak deklaracja zmiennej var.

 
(function(){
    "use strict";
    function foobar(){}; // initial value
    try {
        foobar = "Hello World!"; // new value
        console.log("[no error]");
    } catch(error) {
        console.log("ERROR: " + error.message);
    }
    console.log(foobar, window.foobar);
})();

Co to jest „najbliższy blok”

„Najbliższy blok” to najbliższa „funkcja” (w tym funkcje asynchroniczne, funkcje generatora i asynchroniczne funkcje generatora). Jednakże, co ciekawe, function functionName() {} zachowuje się jak var functionName = function() {}, gdy znajduje się w bloku nie zamykającym do przedmiotów poza wspomnianym zamknięciem. Obserwuj.

  • Normalna var add=function(){}

 
try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}');
  }
} catch(e) {
  console.log("Is a block");
}
var add=function(a, b){return a + b}
  • Normalna function add(){}

 
try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
function add(a, b){
  return a + b;
}
  • Funkcja

 
try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(function () {
    function add(a, b){
      return a + b;
    }
})();
  • Oświadczenie (takie jak if, else, for, while, try/catch/finally, switch, do/while, with)

 
try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
{
    function add(a, b){
      return a + b;
    }
}
  • Funkcja strzałki z var add=function()

 
try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(() => {
    var add=function(a, b){
      return a + b;
    }
})();
  • Funkcja strzałki z function add()

 
try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(() => {
    function add(a, b){
      return a + b;
    }
})();
    
11
2018-11-29 11: 50: 48Z

W JavaScript istnieją dwa sposoby tworzenia funkcji:

  1. Deklaracja funkcji:

     
    function fn(){
      console.log("Hello");
    }
    fn();
    

    Jest to bardzo proste, zrozumiałe, używane w wielu językach i standardach w całej rodzinie języków C. Zadeklarowaliśmy zdefiniowaną funkcję i wykonaliśmy ją wywołując ją.

    Powinieneś wiedzieć, że funkcje są w rzeczywistości obiektami w JavaScript; wewnętrznie stworzyliśmy obiekt dla powyższej funkcji i nadaliśmy mu nazwę o nazwie fn lub odniesienie do obiektut jest przechowywane w fn. Funkcje są obiektami w JavaScript; instancja funkcji jest w rzeczywistości instancją obiektu.

  2. Wyrażenie funkcji:

     
    var fn=function(){
      console.log("Hello");
    }
    fn();
    

    JavaScript ma funkcje pierwszej klasy, czyli tworzy funkcję i przypisuje ją do zmiennej, tak jak tworzysz łańcuch lub numer i przypisujesz go do zmiennej. Tutaj zmienna fn jest przypisana do funkcji. Powodem tej koncepcji są funkcje w JavaScript; fn wskazuje na instancję obiektu powyższej funkcji. Zainicjowaliśmy funkcję i przypisaliśmy ją do zmiennej. Nie wykonuje funkcji i nie przypisuje wyniku.

Odniesienie: Funkcja JavaScript składnia deklaracji: var fn = function () {} vs funkcja fn () {}

    
10
2017-04-09 07: 13: 56Z
  1. co z trzecią opcją, var fn = function fn() {...}?
    2016-08-20 00: 40: 27Z
  2. Cześć Chharvey, nie jestem pewien co do pytania, myślę, że mówisz o wyrażeniu funkcji, o którym już wspomniałem. Jeśli jednak nadal jest jakieś zamieszanie, po prostu bądź bardziej wyszukany.
    2016-08-23 10: 00: 44Z
  3. yes Pytałem o wyrażenie funkcji o nazwie . jest podobny do opcji # 2, z wyjątkiem tego, że funkcja ma identyfikator. zazwyczaj ten identyfikator jest taki sam jak zmienna, do której jest przypisany, ale nie zawsze tak jest.
    2016-08-23 10: 39: 46Z
  4. Tak Nazwane wyrażenie funkcji jest podobne do mojej opcji # 2. Posiadanie identyfikatora nie jest obowiązkowe, ponieważ nie jest używane. Za każdym razem, gdy będziesz wykonywać wyrażenie funkcji, użyjesz zmiennej przechowującej obiekt funkcji. Identyfikator nie ma żadnego celu.
    2016-08-23 11: 42: 19Z

Oba są różnymi sposobami definiowania funkcji. Różnica polega na tym, jak przeglądarka interpretuje i ładuje je do kontekstu wykonania.

Pierwszy przypadek dotyczy wyrażeń funkcji, które ładują się tylko wtedy, gdy interpreter osiągnie tę linię kodu. Jeśli zrobisz to w następujący sposób, pojawi się błąd, że funkcja One nie jest funkcją .

 
functionOne();
var functionOne = function() {
    // Some code
};

Powodem jest to, że w pierwszej linii żadna wartość nie jest przypisana do funkcji, a zatem jest niezdefiniowana. Próbujemy nazwać to funkcją, a więc otrzymujemy błąd.

W drugim wierszu przypisujemy referencję anonimowej funkcji do funkcjiOne.

Drugi przypadek dotyczy deklaracji funkcji, które ładują się przed wykonaniem dowolnego kodu. Więc jeśli podoba ci się to, nie otrzymasz żadnego błędu, ponieważ deklaracja ładuje się przed wykonaniem kodu.

 
functionOne();
function functionOne() {
   // Some code
}
    
9
2015-12-28 20: 42: 20Z

Informacje o skuteczności:

Nowe wersje V8 wprowadziły kilka optymalizacji pod maską, podobnie jak SpiderMonkey.

Prawie nie ma teraz różnicy między wyrażeniem a deklaracją.
Wyrażenie funkcji wydaje się być szybsze teraz.

Chrome 62.0.3202 „Test

FireFox 55 „Test

Chrome Canary 63.0.3225 „Test


  

Anonymous wyrażeń funkcji wydaje się mieć lepszą wydajność   przeciwko Named wyrażeniu funkcji.


Firefox „Firefox Kanarek Chrome „Kanarek Chrome „Chrome

    
9
2017-09-28 05: 13: 17Z
  1. Tak, ta różnica jest tak niewielka, że ​​miejmy nadzieję, że devs będą się zajmować tym, które podejście jest bardziej możliwe do utrzymania dla ich specyficznych potrzeb, a nie które może bądź szybszy (otrzymasz różne wyniki jsperf przy każdej próbie, w zależności od tego, co robi przeglądarka - większość zadań javascript nie musi zajmować się mikrooptymalizacjami do tego stopnia).
    2017-11-26 01: 41: 53Z
  2. @ squidbe Nie ma różnicy. Zobacz tutaj: jsperf.com/empty-tests-performance
    2018-05-10 21: 10: 00Z

Są dość podobne z małymi różnicami, z których pierwsza jest zmienną przypisaną do funkcji anonimowej (deklaracja funkcji), a druga jest normalnym sposobem tworzenia funkcji w JavaScript (deklaracja funkcji anonimowych), obie mają zastosowanie, minusy i plusy:

1. Wyrażenie funkcji

 
var functionOne = function() {
    // Some code
};
  

Wyrażenie funkcji definiuje funkcję jako część większej   składnia wyrażeń (zazwyczaj przypisanie zmiennej). Funkcje   zdefiniowane za pomocą funkcji Wyrażenia mogą być nazwane lub anonimowe. Funkcjonować   Wyrażenia nie mogą zaczynać się od „funkcji” (stąd nawiasy   wokół poniższego przykładu wywołującego samego siebie.

Przypisz zmienną do funkcji, oznacza to, że Podnoszenie, jak wiemy funkcje w JavaScript mogą Hoist, oznacza, że ​​można je wywołać, zanim zostaną zadeklarowane, podczas gdy zmienne muszą być zadeklarowane przed uzyskaniem dostępu do nich, więc znaczy w tym przypadku nie możemy uzyskać dostępu do funkcji wcześniej niż zadeklarowano, może to być także sposób, w jaki piszesz swoje funkcje, dla funkcji, które zwracają inną funkcję, ten rodzaj deklaracji może mieć sens, również w ECMA6 i amp; powyżej możesz przypisać to do funkcji strzałki, która może być używana do wywoływania funkcji anonimowych, również ten sposób deklarowania jest lepszym sposobem tworzenia funkcji Konstruktora w JavaScript.

2. Deklaracja funkcji

 
function functionTwo() {
    // Some code
}
  

Deklaracja funkcji definiuje nazwaną zmienną funkcji bez   wymagające przypisania zmiennej. Deklaracje funkcji występują jako   samodzielne konstrukcje i nie mogą być zagnieżdżone w blokach niefunkcjonalnych.   Pomyśl o nich jako o rodzeństwie deklaracji zmiennych.   Tak jak deklaracje zmiennych muszą zaczynać się od „var”, funkcja   Deklaracje muszą zaczynać się od „funkcji”.

Jest to normalny sposób wywoływania funkcji w JavaScript, ta funkcja może zostać wywołana, zanim nawet zadeklarujesz ją, tak jak w JavaScript, wszystkie funkcje uzyskują Hoisted, ale jeśli masz „ścisłe użycie”, to nie będzie to Hoist zgodnie z oczekiwaniami, to jest dobrym sposobem na wywołanie wszystkich normalnych funkcji, które nie są duże w liniach i nie są funkcją konstruktora.

Ponadto, jeśli potrzebujesz więcej informacji na temat działania podnośnika w JavaScript, odwiedź poniższy link:

https://developer.mozilla.org/en-US/docs /Glosariusz /Podnoszenie

    
8
2017-07-30 04: 30: 14Z
  1. ...also this way of declaring is a better way to create Constructor functions in JavaScript, czy możesz to wyjaśnić, jestem ciekawy!
    2017-06-13 12: 44: 01Z
  2. Jednym z powodów jest to, że wszystkie wbudowane funkcje Konstruktora w JavaScript zostały utworzone tak, jak ta funkcja Number () {[native code]} i nie należy mylić z wbudowanymi, również odwołującymi się później w in ten przypadek jest bezpieczniejszy i kończy się na czystszym kodzie, ale nie używa się podnoszenia ...
    2017-06-13 12: 56: 45Z

    To są tylko dwa możliwe sposoby deklarowania funkcji, a po drugie, możesz użyć funkcji przed deklaracją.

        
    6
    2015-12-28 20: 32: 45Z
    1. Proszę opracować i podać działające fragmenty kodu
      2018-05-10 21: 06: 22Z

    new Function() można użyć do przekazania ciała funkcji w ciągu. Dzięki temu można wykorzystać do tworzenia dynamicznych funkcji. Również przekazanie skryptu bez wykonania skryptu.

     
    var func = new Function("x", "y", "return x*y;");
    function secondFunction(){
       var result;
       result = func(10,20);
       console.log ( result );
    }
    
    secondFunction()
    
        
    5
    2016-05-10 07: 05: 46Z
    1. Chociaż jest to dobre i prawdziwe, jak dokładnie to samo odnosi się do zadawanego pytania?
      2018-05-10 21: 06: 04Z
źródło umieszczone tutaj