javascript - parameter - js function vs function




var functionName=Funktion(){} vs Funktion Funktionsname(){} (20)

Andere Kommentatoren haben bereits den semantischen Unterschied der beiden oben genannten Varianten behandelt. Ich wollte einen stilistischen Unterschied feststellen: Nur die Variation "Zuweisung" kann eine Eigenschaft eines anderen Objekts festlegen.

Ich baue oft JavaScript-Module mit einem Muster wie folgt:

(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

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

    return exports;
})();

Bei diesem Muster verwenden alle öffentlichen Funktionen die Zuweisung, während Ihre privaten Funktionen die Deklaration verwenden.

(Beachten Sie auch, dass die Zuweisung nach der Anweisung ein Semikolon erfordern sollte, während die Deklaration dies verbietet.)

Ich habe vor kurzem damit begonnen, den JavaScript-Code eines anderen Benutzers zu pflegen. Ich korrigiere Fehler, füge Funktionen hinzu und versuche, den Code aufzuräumen und ihn einheitlicher zu gestalten.

Der bisherige Entwickler verwendet zwei Möglichkeiten, Funktionen zu deklarieren, und ich kann nicht herausfinden, ob es einen Grund gibt oder nicht.

Die zwei Möglichkeiten sind:

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

Was sind die Gründe für die Verwendung dieser zwei verschiedenen Methoden und welche Vor- und Nachteile haben beide? Gibt es etwas, das mit einer Methode möglich ist, mit der anderen Methode nicht?


Der Unterschied besteht darin, dass functionOne ein Funktionsausdruck ist und daher nur definiert wird, wenn diese Zeile erreicht ist, während functionTwo eine Funktionsdeklaration ist und definiert wird, sobald die umgebende Funktion oder das Skript ausgeführt wird (aufgrund des hoisting ).

Zum Beispiel einen Funktionsausdruck:

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

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

Und eine Funktionsdeklaration:

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

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

Das bedeutet auch, dass Sie Funktionen nicht mit Funktionsdeklarationen bedingt definieren können:

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

Das obige definiert eigentlich functionThree unabhängig vom test - es sei denn, die use strict ist in Kraft. In diesem Fall wird einfach ein Fehler ausgegeben.


Ein Beispiel dafür, wann Sie die erste Methode der zweiten vorziehen sollten, ist, wenn Sie die vorherigen Definitionen einer Funktion nicht überschreiben müssen.

Mit

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

Diese Definition von myfunction setzt alle vorherigen Definitionen außer Kraft, da dies zur myfunction erfolgt.

Während

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

führt den korrekten Job aus, myfunction nur dann zu definieren, wenn die condition erfüllt ist.


Ein wichtiger Grund ist, eine und nur eine Variable als "Root" Ihres Namespaces hinzuzufügen ...

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

}

oder

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

Es gibt viele Techniken zum Namensraum. Mit der Fülle an verfügbaren JavaScript-Modulen wird dies immer wichtiger.

Siehe auch Wie deklariere ich einen Namespace in JavaScript?


Hier ist der Überblick über die Standardformulare, die Funktionen erstellen: (Ursprünglich für eine andere Frage geschrieben, aber angepasst, nachdem sie in die kanonische Frage verschoben wurde.)

Bedingungen:

Die Schnellliste:

  • Funktionserklärung

  • "Anonyme" function Expression (die trotz des Begriffs manchmal Funktionen mit Namen erstellt)

  • Benannte function Ausdruck

  • Accessor-Funktionsinitialisierer (ES5 +)

  • Arrow Funktionsausdruck (ES2015 +) (der wie anonyme Funktionsausdrücke keinen expliziten Namen enthält und dennoch Funktionen mit Namen erstellen kann)

  • Methodendeklaration im Objektinitialisierer (ES2015 +)

  • Konstruktor- und Methodendeklarationen in der class (ES2015 +)

Funktionserklärung

Das erste Formular ist eine Funktionsdeklaration , die folgendermaßen aussieht:

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

Eine Funktionsdeklaration ist eine Deklaration . Es ist keine Aussage oder ein Ausdruck. Als solches folgen Sie nicht mit einem ; (obwohl dies harmlos ist).

Eine Funktionsdeklaration wird verarbeitet, wenn die Ausführung in den Kontext eintritt, in dem sie erscheint, bevor ein Schritt-für-Schritt-Code ausgeführt wird. Die von ihr erstellte Funktion erhält einen eigenen Namen ( x im obigen Beispiel), und dieser Name wird in den Bereich gesetzt, in dem die Deklaration angezeigt wird.

Da es vor jedem Schritt-für-Schritt-Code im selben Kontext verarbeitet wird, können Sie Folgendes tun:

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

Bis ES2015 deckte die Spezifikation nicht ab, was eine JavaScript-Engine tun soll, wenn Sie eine Funktionsdeklaration in eine Kontrollstruktur wie try , if , switch , while usw. einfügen:

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

Und da sie verarbeitet werden, bevor Schritt für Schritt Code ausgeführt wird, ist es schwierig zu wissen, was zu tun ist, wenn sie sich in einer Kontrollstruktur befinden.

Obwohl dies vor ES2015 nicht angegeben wurde , war dies eine zulässige Erweiterung zur Unterstützung von Funktionsdeklarationen in Blöcken. Leider (und unausweichlich) haben verschiedene Motoren unterschiedliche Dinge getan.

Ab ES2015 gibt die Spezifikation an, was zu tun ist. In der Tat gibt es drei verschiedene Dinge zu tun:

  1. Wenn im lockeren Modus kein Webbrowser vorhanden ist, soll die JavaScript-Engine eine Sache tun
  2. Im lockeren Modus eines Webbrowsers soll die JavaScript-Engine etwas anderes tun
  3. Im strikten Modus (Browser oder nicht) soll die JavaScript-Engine noch etwas anderes tun

Die Regeln für die losen Modi sind schwierig, aber im strikten Modus sind Funktionsdeklarationen in Blöcken einfach: Sie sind lokal für den Block (sie haben Blockbereich , der in ES2015 ebenfalls neu ist) und werden nach oben gehoben des Blocks. So:

"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)

"Anonyme" function Ausdruck

Die zweite allgemeine Form wird als anonymer Funktionsausdruck bezeichnet :

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

Wie alle Ausdrücke wird es ausgewertet, wenn es bei der schrittweisen Ausführung des Codes erreicht wird.

In ES5 hat die erstellte Funktion keinen Namen (sie ist anonym). In ES2015 erhält die Funktion nach Möglichkeit einen Namen, indem sie aus dem Kontext abgeleitet wird. Im obigen Beispiel wäre der Name y . Ähnliches geschieht, wenn die Funktion der Wert eines Eigenschaftsinitialisierers ist. (Für Details zum Zeitpunkt und zu den Regeln suchen SetFunctionName in der Spezifikation nach SetFunctionName - es wird überall angezeigt.)

Benannte function Ausdruck

Die dritte Form ist ein benannter Funktionsausdruck ("NFE"):

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

Die Funktion, die erstellt wird, hat einen eigenen Namen (in diesem Fall w ). Wie alle Ausdrücke wird diese ausgewertet, wenn sie bei der schrittweisen Ausführung des Codes erreicht wird. Der Name der Funktion wird nicht zu dem Bereich hinzugefügt, in dem der Ausdruck angezeigt wird. Der Name ist in der Funktion selbst enthalten:

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

Beachten Sie, dass NFEs häufig eine Fehlerquelle für JavaScript-Implementierungen waren. IE8 und frühere Versionen behandeln beispielsweise NFEs völlig falsch und erstellen zwei verschiedene Funktionen zu zwei verschiedenen Zeitpunkten. Frühe Versionen von Safari hatten ebenfalls Probleme. Die gute Nachricht ist, dass aktuelle Versionen von Browsern (IE9 und höher, aktuelle Safari) diese Probleme nicht mehr haben. (Zum jetzigen Zeitpunkt ist IE8 leider weit verbreitet, weshalb die Verwendung von NFEs mit Code für das Web im Allgemeinen immer noch problematisch ist.)

Accessor-Funktionsinitialisierer (ES5 +)

Manchmal schleichen sich Funktionen weitgehend unbemerkt ein. das ist bei Accessor-Funktionen der Fall. Hier ist ein Beispiel:

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"

Beachten Sie, dass ich bei der Verwendung der Funktion nicht () ! Das liegt daran, dass es sich um eine Accessor-Funktion für eine Eigenschaft handelt. Wir bekommen und setzen die Eigenschaft wie üblich, aber hinter den Kulissen wird die Funktion aufgerufen.

Sie können auch Accessor-Funktionen mit Object.defineProperty , Object.defineProperties und dem weniger bekannten zweiten Argument von Object.create .

Pfeilfunktionsausdruck (ES2015 +)

ES2015 bringt uns die Pfeilfunktion. Hier ist ein Beispiel:

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

Sehen Sie, dass n => n * 2 in der map() versteckt ist? Das ist eine Funktion.

Ein paar Dinge zu Pfeilfunktionen:

  1. Das haben sie nicht. Stattdessen schließen sie das this des Kontextes, in dem sie definiert sind. (Sie schließen auch arguments und, falls zutreffend, super .) Dies bedeutet, dass das in ihnen dasselbe ist wie das, an dem sie erstellt wurden, und nicht geändert werden kann.

  2. Wie Sie bereits bemerkt haben, verwenden Sie die Keyword- function . Verwenden Sie stattdessen => .

Das obige Beispiel n => n * 2 ist eine Form davon. Wenn Sie mehrere Argumente haben, um die Funktion zu übergeben, verwenden Sie Parens:

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

(Denken Sie daran, dass Array#map den Eintrag als erstes Argument und den Index als zweites übergibt.)

In beiden Fällen ist der Körper der Funktion nur ein Ausdruck. Der Rückgabewert der Funktion ist automatisch das Ergebnis dieses Ausdrucks (Sie verwenden keine explizite return ).

Wenn Sie mehr als nur einen einzelnen Ausdruck ausführen, verwenden Sie {} und eine explizite return (wenn Sie einen Wert zurückgeben müssen) wie üblich:

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

Die Version ohne { ... } wird als Pfeilfunktion mit einem Ausdruckskörper oder einem kurzen Körper bezeichnet . (Außerdem: Eine kurze Pfeilfunktion.) Die mit { ... } definierte Körperform ist eine Pfeilfunktion mit einem Funktionskörper . (Auch: Eine verbose Pfeilfunktion.)

Methodendeklaration im Objektinitialisierer (ES2015 +)

ES2015 ermöglicht eine kürzere Form der Deklaration einer Eigenschaft, die auf eine Funktion verweist. es sieht aus wie das:

var o = {
    foo() {
    }
};

Das Äquivalent in ES5 und früher wäre:

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

Konstruktor- und Methodendeklarationen in der class (ES2015 +)

ES2015 enthält class , einschließlich deklarierter Konstruktoren und Methoden:

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

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

Es gibt zwei Funktionsdeklarationen: Eine für den Konstruktor, der den Namen Person erhält, und eine für getFullName , eine Funktion, die Person.prototype zugewiesen Person.prototype .


Wenn Sie über den globalen Kontext sprechen, erzeugen sowohl die var Anweisung als auch eine FunctionDeclaration am Ende eine nicht löschbare Eigenschaft für das globale Objekt. Der Wert von beiden kann jedoch überschrieben werden .

Der kleine Unterschied zwischen den beiden Möglichkeiten besteht darin, dass bei Ausführung des Variablen-Instantiierungsprozesses (vor der eigentlichen Codeausführung) alle mit var deklarierten Bezeichner mit undefined initialisiert werden und die von den FunctionDeclaration verwendeten seit diesem Moment verfügbar sind Beispiel:

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

Die Zuweisung des FunctionExpression erfolgt bis zur Laufzeit.

Eine globale Eigenschaft, die von einer FunctionDeclaration kann wie ein Variablenwert problemlos überschrieben werden, z.

 function test () {}
 test = null;

Ein weiterer offensichtlicher Unterschied zwischen Ihren beiden Beispielen besteht darin, dass die erste Funktion keinen Namen hat, die zweite jedoch, was beim Debuggen (dh Prüfen eines Aufrufstapels) sehr nützlich sein kann.

Zu Ihrem bearbeiteten ersten Beispiel ( foo = function() { alert('hello!'); }; ) Handelt es sich um eine nicht deklarierte Zuweisung. Ich würde Sie dringend dazu ermutigen, immer das Schlüsselwort var .

Wenn bei einer Zuweisung ohne die var Anweisung der referenzierte Bezeichner nicht in der Gültigkeitsbereichskette gefunden wird, wird er zu einer löschbaren Eigenschaft des globalen Objekts.

Nicht deklarierte Zuweisungen werfen auch einen ReferenceError auf ECMAScript 5 im strengen Modus .

Muss man lesen:

Hinweis : Diese Antwort wurde aus einer anderen Frage zusammengeführt , in der der Hauptzweifel und Missverständnis des OP darin bestand, dass mit einer FunctionDeclaration deklarierte Kennungen nicht überschrieben werden konnten, was nicht der Fall ist.


gibt ein Beispiel, in dem er eine zugewiesene Funktion benennt, um sieshortcut() als interne Referenz auf sich selbst verwenden zu können. John Resig gibt ein anderes Beispiel - das Kopieren einer rekursiven Funktion, die einem anderen Objekt in seinem Lernprogramm für fortgeschrittenes Javascript zugewiesen ist . Während das Zuweisen von Funktionen zu Eigenschaften nicht unbedingt die Frage ist, empfehle ich, das Lernprogramm aktiv auszuprobieren. Führen Sie den Code aus, indem Sie auf die Schaltfläche in der oberen rechten Ecke klicken, und doppelklicken Sie auf den Code, um ihn nach Belieben zu bearbeiten.

Beispiele aus dem Tutorial: rekursive Aufrufe in yell():

Tests schlagen fehl, wenn das ursprüngliche Ninja-Objekt entfernt wird. (Seite 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?" ); 
}

Wenn Sie die Funktion nennen, die rekursiv aufgerufen wird, werden die Tests bestanden. (Seite 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." );

new Function()kann verwendet werden, um den Rumpf der Funktion in einem String zu übergeben. Und damit können dynamische Funktionen erstellt werden. Das Skript auch übergeben, ohne das Skript auszuführen.

var func = new Function("x", "y", "return x*y;");
function secondFunction(){
   var result;
   result = func(10,20);
   console.log ( result );
}

secondFunction()

Über die Leistung:

In neuen Versionen V8wurden mehrere Optimierungen unter der Haube eingeführt SpiderMonkey.

Es gibt jetzt fast keinen Unterschied zwischen Ausdruck und Deklaration.
Der Funktionsausdruck scheint jetzt schneller zu sein .

Chrome 62.0.3202

FireFox 55

Chrome Canary 63.0.3225


AnonymousFunktionsausdrücke scheinen eine bessere Leistung gegenüber NamedFunktionsausdrücken zu haben .


Firefox Chrome Canary Chrom


Das erste Beispiel ist eine Funktionsdeklaration:

function abc(){}

Das zweite Beispiel ist ein Funktionsausdruck:

var abc = function() {};

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

Einfach gesagt:

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

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

Um mehr über dieses Thema zu erfahren, empfehle ich Ihnen diesen link


Dies sind nur zwei Möglichkeiten, Funktionen zu deklarieren, und zweitens können Sie die Funktion vor der Deklaration verwenden.


Ein weiterer Unterschied, der in den anderen Antworten nicht erwähnt wird, besteht darin, dass Sie die anonyme Funktion verwenden

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

und benutze das als Konstruktor wie in

var one = new functionOne();

dann one.constructor.namewird nicht definiert. Function.nameist kein Standard, wird jedoch von Firefox, Chrome, anderen Webkit-Browsern und IE 9+ unterstützt.

Mit

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

Es ist möglich, den Namen des Konstruktors als String mit abzurufen two.constructor.name.


Es gibt drei bemerkenswerte Vergleiche zwischen den zwei verschiedenen Funktionsdeklarationen, die unten aufgeführt sind.

  1. Verfügbarkeit (Umfang) der Funktion

Folgendes funktioniert, weil function add()es auf den nächsten Block beschränkt ist:

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

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

Folgendes funktioniert nicht (weil das das var add=übertrifft function add()).

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

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

Folgendes funktioniert nicht, da addes nach seiner Verwendung deklariert wird.

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

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

  1. (Funktion) .name

Der Name einer Funktion function thefuncname(){}ist der Funktionsname, wenn sie auf diese Weise deklariert wird.

function foobar(a, b){}

console.log(foobar.name);

var a = function foobar(){};

console.log(a.name);

Wenn eine Funktion als deklariert ist function(){}, ist ansonsten die Funktion .name die erste Variable, in der die Funktion gespeichert wird.

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

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

Wenn für die Funktion keine Variablen festgelegt sind, ist der Funktionsname der leere String ( "").

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

Während die Variable, der die Funktion ursprünglich zugewiesen wird, den Namen festlegt, ändern aufeinanderfolgende, auf die Funktion gesetzte Variablen den Namen nicht.

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

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

  1. Performance

In Googles V8 und Firefox's Spidermonkey kann es einige Mikrosekunden-JIST-Kompilierungsunterschiede geben, aber letztendlich ist das Ergebnis das gleiche. Um dies zu beweisen, untersuchen wir die Effizienz von JSPerf bei Mikrobenchmarks durch Vergleichen der Geschwindigkeit zweier leerer Codeausschnitte. Die JSPerf-Tests finden Sie hier . Und die Tests von jsben.ch finden Sie hier . Wie Sie sehen, gibt es einen merklichen Unterschied, wenn es keinen geben sollte. Wenn Sie wirklich ein Performance-Freak wie ich sind, lohnt es sich vielleicht mehr, zu versuchen, die Anzahl der Variablen und Funktionen im Gültigkeitsbereich zu reduzieren und insbesondere den Polymorphismus zu eliminieren (beispielsweise die Verwendung derselben Variablen zum Speichern zweier verschiedener Typen).

Was ist der "nächstgelegene Block"

Der "nächste Block" ist die nächstgelegene "Funktion" (einschließlich asynchroner Funktionen, Generatorfunktionen und asynchroner Generatorfunktionen). Interessanterweise function functionName() {}verhält sich a jedoch wie ein var functionName = function() {}in einem Nicht-Verschlussblock befindlicher Gegenstand außerhalb des Verschlusses. Beobachten.

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


Gregs Answer ist gut genug, aber ich möchte noch etwas hinzufügen, was ich gerade bei Douglas Crockfords Videos gelernt habe .

Funktionsausdruck:

var foo = function foo() {};

Funktionsaussage:

function foo() {};

Die Funktionsanweisung ist nur eine Abkürzung für varAnweisung mit einem functionWert.

So

function foo() {};

erweitert zu

var foo = function foo() {};

Welche weiter ausdehnt auf:

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

Und beide werden an den Anfang des Codes angehoben.


Ich liste die Unterschiede unten auf:

  1. Eine Funktionsdeklaration kann an beliebiger Stelle im Code platziert werden. Auch wenn es aufgerufen wird, bevor die Definition im Code erscheint, wird sie ausgeführt, wenn die Funktionsdeklaration in den Speicher geschrieben oder auf eine Weise angehoben wird, bevor ein anderer Code auf der Seite die Ausführung startet.

    Schauen Sie sich die Funktion unten an:

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

    Dies liegt daran, dass es während der Ausführung wie folgt aussieht:

    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
    

    Wenn ein Funktionsausdruck vor dem Aufruf nicht definiert wurde, führt dies zu einem Fehler. Auch hier wird die Funktionsdefinition selbst nicht nach oben verschoben oder wie in den Funktionsdeklarationen in den Speicher geschrieben. Die Variable, der wir die Funktion zuweisen, wird jedoch angehoben, undefined wird ihr zugewiesen.

    Gleiche Funktion mit Funktionsausdrücken:

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

    Dies liegt daran, dass es während der Ausführung so aussieht:

    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. Es ist nicht sicher, Funktionsdeklarationen in Nichtfunktionsblöcken zu schreiben, z. B. wenn auf sie nicht zugegriffen werden kann.

    if (test) {
        function x() { doSomething(); }
    }
    
  3. Benannte Funktionsausdrücke wie der unten stehende funktionieren möglicherweise nicht in Internet Explorer-Browsern vor Version 9.

    var today = function today() {return new Date()}
    

Ich verwende den variablen Ansatz in meinem Code aus einem ganz bestimmten Grund, dessen Theorie oben abstrakt beschrieben wurde, aber ein Beispiel könnte einigen Leuten wie mir mit begrenztem JavaScript-Know-how helfen.

Ich habe Code, den ich mit 160 unabhängig entwickelten Brandings ausführen muss. Der größte Teil des Codes befindet sich in gemeinsam genutzten Dateien, Branding-spezifische Inhalte befinden sich jedoch in einer separaten Datei, und zwar für jedes Branding.

Einige Brandings erfordern bestimmte Funktionen, andere nicht. Manchmal muss ich neue Funktionen hinzufügen, um brandneue spezifische Dinge zu tun. Ich bin froh, den gemeinsam genutzten Code zu ändern, aber ich möchte nicht alle 160 Branding-Dateien ändern.

Mit der Variablensyntax kann ich die Variable (im Wesentlichen einen Funktionszeiger) im gemeinsam genutzten Code deklarieren und entweder eine triviale Stub-Funktion zuweisen oder auf null setzen.

Die ein oder zwei Brandings, für die eine bestimmte Implementierung der Funktion erforderlich ist, können ihre Version der Funktion definieren und diese der Variablen zuweisen, wenn sie möchten, und der Rest tut nichts. Ich kann auf eine Nullfunktion testen, bevor ich sie im gemeinsam genutzten Code ausführen kann.

Aus den obigen Kommentaren der Leute ist ersichtlich, dass es auch möglich ist, eine statische Funktion neu zu definieren, aber ich denke, die variable Lösung ist schön und klar.


In JavaScript gibt es zwei Möglichkeiten, Funktionen zu erstellen:

  1. Funktionsdeklaration:

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

    Dies ist sehr einfach, selbsterklärend, wird in vielen Sprachen verwendet und ist in der gesamten C-Sprachfamilie Standard. Wir haben eine Funktion als definiert deklariert und durch Aufruf ausgeführt.

    Sie sollten wissen, dass Funktionen eigentlich Objekte in JavaScript sind. intern haben wir ein Objekt für die obige Funktion erstellt und ihm einen Namen namens fn gegeben oder die Referenz auf das Objekt wird in fn gespeichert. Funktionen sind Objekte in JavaScript. Eine Instanz einer Funktion ist eigentlich eine Objektinstanz.

  2. Funktionsausdruck:

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

    JavaScript verfügt über erstklassige Funktionen, dh Sie erstellen eine Funktion und weisen sie einer Variablen zu, genauso wie Sie einen String oder eine Zahl erstellen und einer Variablen zuweisen. Hier wird die Variable fn einer Funktion zugewiesen. Der Grund für dieses Konzept ist, dass Funktionen Objekte in JavaScript sind. fn zeigt auf die Objektinstanz der obigen Funktion. Wir haben eine Funktion initialisiert und einer Variablen zugewiesen. Die Funktion wird nicht ausgeführt und das Ergebnis zugewiesen.

Referenz: JavaScript-Funktionsdeklarationssyntax: var fn = function () {} vs function fn () {}


Moderne JavaScript-Engines sind angesichts des Arguments "benannte Funktionen werden in Stapelverfolgungen sichtbar" durchaus in der Lage, anonyme Funktionen darzustellen.

Zum jetzigen Zeitpunkt beziehen sich V8, SpiderMonkey, Chakra und Nitro immer auf benannte Funktionen. Sie beziehen sich fast immer auf eine anonyme Funktion anhand ihrer Kennung, falls vorhanden.

SpiderMonkey kann den Namen einer anonymen Funktion ermitteln, die von einer anderen Funktion zurückgegeben wird. Der Rest kann nicht.

Wenn Sie wirklich wollten, dass Ihre Iterator- und Erfolgs-Callbacks in der Ablaufverfolgung angezeigt werden, könnten Sie diese auch nennen ...

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

Aber zum größten Teil ist es nicht wert, betont zu werden.

Geschirr ( 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

Spinnenaffe

func.name: 
Trace:
[email protected]://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


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


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


func.name: 
Trace:
[email protected]://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


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


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


func.name: 
Trace:
[email protected]://localhost:8000/test.js:17:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


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


func.name: l
Trace:
[email protected]://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:
[email protected]://localhost:8000/test.js:33:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


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

Chakra

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:
[email protected]://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

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

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

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

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

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

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

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

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

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

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

func.name: p
Trace:
[email protected]://localhost:8000/test.js:38:30
http://localhost:8000/test.js:47:13
[email protected][native code]
global [email protected]://localhost:8000/test.js:44:33

Wenn Sie diese Funktionen zum Erstellen von Objekten verwenden würden, würden Sie Folgendes erhalten:

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

Beides sind verschiedene Arten, eine Funktion zu definieren. Der Unterschied besteht darin, wie der Browser sie interpretiert und in einen Ausführungskontext lädt.

Der erste Fall betrifft Funktionsausdrücke, die nur geladen werden, wenn der Interpreter diese Codezeile erreicht. Wenn Sie dies wie folgt tun, erhalten Sie eine Fehlermeldung, dass das functionOne keine Funktion ist .

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

Der Grund ist, dass in der ersten Zeile functionOne kein Wert zugewiesen wird und daher undefiniert ist. Wir versuchen, es als Funktion zu bezeichnen, und daher erhalten wir einen Fehler.

In der zweiten Zeile weisen wir functionOne die Referenz einer anonymen Funktion zu.

Der zweite Fall betrifft Funktionsdeklarationen, die geladen werden, bevor Code ausgeführt wird. Wenn Sie also Folgendes mögen, erhalten Sie keine Fehler, wenn die Deklaration vor der Codeausführung geladen wird.

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




idioms