7585 Stimmen

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

Ich habe vor kurzem damit begonnen, den JavaScript-Code von jemand anderem zu pflegen. Ich behebe Fehler, füge Funktionen hinzu und versuche, den Code aufzuräumen und konsistenter zu machen.

Der vorherige Entwickler verwendete zwei Arten, Funktionen zu deklarieren, und ich kann nicht herausfinden, ob es einen Grund dafür gibt oder nicht.

Es gibt zwei Möglichkeiten:

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

function functionTwo() {
    // Some code
}

Was sind die Gründe für die Verwendung dieser beiden unterschiedlichen Methoden und was sind die Vor- und Nachteile der jeweiligen Methode? Gibt es irgendetwas, das mit der einen Methode gemacht werden kann, was mit der anderen nicht möglich ist?

51voto

Leon Gaban Punkte 31681

Ich füge meine eigene Antwort hinzu, nur weil alle anderen den Teil mit dem Heben gründlich behandelt haben.

Ich habe mich schon lange gefragt, welcher Weg besser ist, und dank der http://jsperf.com jetzt weiß ich es :)

enter image description here

Funktionsdeklarationen sind schneller, und darauf kommt es bei der Webentwicklung doch an, oder? ;)

0 Stimmen

Siehe Antwort zur Leistung unten , unterschiedliche Ergebnisse

50voto

Jack G Punkte 3797

.

  1. Verfügbarkeit (Umfang) der Funktion

Das Folgende funktioniert, weil function add() ist auf den nächstgelegenen Block skaliert:

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

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

Das folgende Beispiel funktioniert nicht, da die Variable aufgerufen wird, bevor der Variablen ein Funktionswert zugewiesen wird add .

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

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

Der obige Code ist in seiner Funktionalität identisch mit dem nachstehenden Code. Beachten Sie, dass die explizite Zuweisung von add = undefined ist überflüssig, denn es genügt, die var add; ist genau dasselbe wie var add=undefined .

var add = undefined;

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

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

Das Folgende funktioniert nicht, weil var add= beginnt einen Ausdruck und bewirkt Folgendes function add() ein Ausdruck anstelle eines Blocks zu sein. Benannte Funktionen sind nur für sich selbst und den sie umgebenden Block sichtbar. Als function add() hier ein Ausdruck ist, hat er keinen umgebenden Block, ist also nur für sich selbst sichtbar.

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

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

Der Name einer Funktion function thefuncname(){} es thefuncname wenn es auf diese Weise deklariert wird.

function foobar(a, b){}

console.log(foobar.name);

var a = function foobar(){};

console.log(a.name);

Andernfalls, wenn eine Funktion deklariert ist als function(){} El Funktion .name ist die erste Variable, die zum Speichern der Funktion verwendet wird.

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

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

Wenn der Funktion keine Variablen zugewiesen sind, ist der Funktionsname eine leere Zeichenkette ( "" ).

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

Schließlich legt die Variable, der die Funktion zugewiesen ist, zunächst den Namen fest, während nachfolgende Variablen, die der Funktion zugewiesen werden, den Namen nicht ändern.

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

console.log(a.name);
console.log(b.name);
console.log(c.name);
  1. Leistung

In Googles V8 und Firefox' Spidermonkey mag es einen Unterschied von ein paar Mikrosekunden bei der JIT-Kompilierung geben, aber letztlich ist das Ergebnis genau dasselbe. Um dies zu beweisen, wollen wir die Effizienz von JSPerf bei Mikro-Benchmarks untersuchen, indem wir die Geschwindigkeit von zwei leeren Codeschnipseln vergleichen. Die JSPerf-Tests finden Sie hier . Und, die jsben.ch Tests finden Sie hier . Wie Sie sehen können, gibt es einen spürbaren Unterschied, wenn es keinen geben sollte. Wenn Sie wie ich ein echter Leistungsfanatiker sind, sollten Sie versuchen, die Anzahl der Variablen und Funktionen im Anwendungsbereich zu reduzieren und vor allem Polymorphismus zu vermeiden (z. B. die Verwendung derselben Variablen zur Speicherung zweier unterschiedlicher Typen).

  1. Variable Veränderlichkeit

Wenn Sie die var um eine Variable zu deklarieren, können Sie der Variablen einen anderen Wert zuweisen, etwa so.

(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);
})();

Wenn wir jedoch die const-Anweisung verwenden, wird der Variablenverweis unveränderlich. Das bedeutet, dass wir der Variablen keinen neuen Wert zuweisen können. Bitte beachten Sie jedoch, dass der Inhalt der Variablen dadurch nicht unveränderlich wird: Wenn Sie const arr = [] dann können Sie immer noch arr[10] = "example" . Nur etwas tun wie arr = "new value" o arr = [] würde einen Fehler auslösen (siehe unten).

(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);
})();

Interessanterweise, wenn wir die Variable deklarieren als function funcName(){} ist die Unveränderlichkeit der Variablen die gleiche wie bei der Deklaration mit 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);
})();

" "

Der "nächstgelegene Block" ist die nächstgelegene "Funktion" (einschließlich asynchroner Funktionen, Generatorfunktionen und asynchroner Generatorfunktionen). Interessant ist jedoch, dass ein function functionName() {} verhält sich wie ein var functionName = function() {} in einem nicht verschlossenen Block auf Gegenstände außerhalb dieses Verschlusses. Beachten Sie.

  • Normal 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}

  • Normal 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; }

  • Funktion

    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; } })();

  • Anweisung (wie z.B. 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; } }

  • Pfeilfunktion mit 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; } })();

  • Pfeilfunktion mit 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; } })();

41voto

eljenso Punkte 16300

Eine Funktionsdeklaration und ein Funktionsausdruck, der einer Variablen zugewiesen ist, verhalten sich gleich, sobald die Bindung hergestellt ist.

Es gibt jedoch einen Unterschied bei wie y wenn das Funktionsobjekt ist tatsächlich mit seiner Variablen verbunden. Dieser Unterschied ist auf den Mechanismus zurückzuführen, der variables Heben in JavaScript.

Grundsätzlich werden alle Funktionsdeklarationen und Variablendeklarationen an den Anfang der Funktion in der die Deklaration vorkommt (deshalb sagt man, dass JavaScript über Funktionsumfang ).

  • Wenn eine Funktionsdeklaration hochgezogen wird, "folgt" der Funktionskörper Wenn also der Funktionsrumpf ausgewertet wird, wird die Variable sofort an ein Funktionsobjekt gebunden werden.

  • Wenn eine Variablendeklaration hochgezogen wird, erfolgt die Initialisierung no folgen, sondern wird "zurückgelassen". Die Variable wird initialisiert auf undefined am Anfang des Funktionskörpers, und wird zugewiesen einen Wert an seiner ursprünglichen Stelle im Code. (Tatsächlich wird ihm ein Wert zugewiesen an jede Stelle, an der eine Deklaration einer Variablen mit demselben Namen vorkommt).

Auch die Reihenfolge des Hochziehens ist wichtig: Funktionsdeklarationen haben Vorrang vor gleichnamigen Variablendeklarationen, und die letzte Funktionsdeklaration hat Vorrang vor vorhergehenden Funktionsdeklarationen mit demselben Namen.

Einige Beispiele...

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

Variabel foo wird an den Anfang der Funktion gehievt, initialisiert auf undefined , so dass !foo es true also foo zugeordnet ist 10 . Die foo außerhalb von bar Der Geltungsbereich der Richtlinie spielt keine Rolle und bleibt unangetastet.

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

Funktionsdeklarationen haben Vorrang vor Variablendeklarationen, und die letzte Funktionsdeklaration "bleibt hängen".

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

In diesem Beispiel a wird mit dem Funktionsobjekt initialisiert, das sich aus der Auswertung der zweiten Funktionsdeklaration ergibt, und anschließend wird ihm 4 .

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

Hier wird zuerst die Funktionsdeklaration hochgezogen, die Variable deklariert und initialisiert a . Anschließend wird diese Variable zugewiesen 10 . Mit anderen Worten: Die Zuweisung wird nicht der äußeren Variablen zugewiesen. a .

38voto

sla55er Punkte 761

Das erste Beispiel ist eine Funktionsdeklaration:

function abc(){}

Das zweite Beispiel ist ein Funktionsausdruck:

var abc = function() {};

Der Hauptunterschied besteht darin, wie sie gehoben (angehoben und deklariert) werden. Im ersten Beispiel wird die gesamte Funktionsdeklaration angehoben. Im zweiten Beispiel wird nur die var "abc" angehoben, ihr Wert (die Funktion) ist undefiniert, und die Funktion selbst bleibt an der Stelle, an der sie deklariert wurde.

Um es einfach auszudrücken:

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

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

Wenn Sie mehr über dieses Thema erfahren möchten, empfehle ich Ihnen Folgendes enlace

37voto

Sasha Firsov Punkte 671

Im Hinblick auf die Kosten der Codepflege sind benannte Funktionen vorzuziehen:

  • Unabhängig von dem Ort, an dem sie deklariert werden (aber immer noch begrenzt durch den Geltungsbereich).
  • Widerstandsfähiger gegen Fehler wie bedingte Initialisierung (Sie können immer noch überschreiben, wenn Sie wollen).
  • Der Code wird durch die Zuweisung lokaler Funktionen getrennt von der Bereichsfunktionalität besser lesbar. Normalerweise steht im Anwendungsbereich die Funktionalität an erster Stelle, gefolgt von den Deklarationen der lokalen Funktionen.
  • In einem Debugger sehen Sie deutlich den Funktionsnamen auf dem Aufrufstapel anstelle einer "anonymen/evaluierten" Funktion.

Ich vermute, dass weitere PROS für benannte Funktionen folgen werden. Und was als Vorteil von benannten Funktionen aufgeführt ist, ist ein Nachteil für anonyme Funktionen.

Historisch gesehen entstanden anonyme Funktionen aus der Unfähigkeit von JavaScript als Sprache, Mitglieder mit benannten Funktionen aufzulisten:

{
    member:function() { /* How do I make "this.member" a named function? */
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X