Frage Der beste Weg, um eine Funktion zu definieren?


Ich werde immer gelernt, eine Funktion in JavaScript wie folgt zu definieren:

function myFunction(arg1, arg2) { ... }

Ich habe gerade gelesen Google's Anleitung für JavascriptEs sollte erwähnt werden, dass ich Methoden wie folgt definieren sollte:

Foo.prototype.bar = function() { ... };

Frage: Ist "Foo" im Beispiel ein Objekt, oder ist es ein Namensraum? Warum ist das Google-Beispiel nicht der folgende Code (der nicht funktioniert):

prototype.bar = function() { ... };

AKTUALISIEREN: Wenn es hilft zu wissen, wird mein gesamtes JavaScript vom Browser des Benutzers für meine Web-Anwendung aufgerufen.


13
2017-07-18 03:41


Ursprung


Antworten:


Ihre zwei Beispiele sind nicht funktional gleichwertig. Das erste Beispiel definiert einfach eine Funktion (wahrscheinlich eine globale, sofern Sie sie nicht innerhalb einer anderen Funktion definieren). Das zweite Beispiel erweitert den Prototyp eines Konstruktors. Stellen Sie sich vor, Sie fügen der Klasse eine Methode hinzu Foo.

Sofern Sie keine JavaScript-Bibliothek erstellen, wäre mein Vorschlag, keines zu verwenden und irgendeine Art von Namespacesystem zu verwenden. Erstellen Sie ein einzelnes globales Objekt, das als ein Namespace fungiert, über den Sie auf alle Ihre Funktionen zugreifen können.

var MyObject = {
    utils: {
        someUtil: function() {},
        anotherUtil: function() {}
    },
    animation: {
        // A function that animates something?
        animate: function(element) {}
    }
};

Dann:

// Assuming jQuery, but insert whatever library here
$('.someClass').click(function() {
    MyObject.animation.animate(this);
});

Wenn Sie Klassen in JavaScript emulieren möchten, definieren Sie die "Klasse" als Funktion (die Funktion selbst ist der Konstruktor) und fügen dann Methoden über die Funktion hinzu prototype Eigentum.

function Foo() {
    // This is the constructor--initialize any properties
    this.a = 5;
}
// Add methods to the newly defined "class"
Foo.prototype = {
    doSomething: function() { /*...*/ },
    doSomethingElse: function() { /*...*/ }
};

Dann:

var bar = new Foo();
console.log(bar.a); // 5
bar.doSomething();
// etc...

8
2017-07-18 03:58



Ich werde immer gelernt, eine Funktion in JavaScript wie folgt zu definieren:   function myFunction(arg1, arg2) { ... }

Es gibt zwei Möglichkeiten, eine Funktion zu definieren. Entweder als Funktionsdeklaration

function foo(...) {
    ...
}

Oder als Funktionsausdruck

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

Lesen  Mehr  Hier.

Wie auch immer, ich habe gerade den Google-Leitfaden zu Javascript gelesen. Ich erwähnte, dass ich Methoden wie diese definieren sollte: Foo.prototype.bar = function() { ... };

Dies bezieht sich insbesondere auf die Methodenerstellung für Objekte, nicht nur auf normale, eigenständige Funktionen. Angenommen, Sie haben die Basisobjektdeklaration:

var Foo = function() {
    ...
};

Wie bei jeder anderen Zuweisung müssen Sie zur Zuweisung einer Funktion an die Eigenschaft eines Objekts einen Zuweisungsausdruck verwenden. Sie können dies auf zwei Arten tun. Der prägnante und übliche Weg (wie von Googles Referenz vorgeschlagen)

Foo.prototype.bar = function() {};

Oder wenn Sie die deklarative Form der Definition von Funktionen weiterhin verwenden möchten

function bar() {
    ...
};
Foo.prototype.bar = bar;

Dies ist normalerweise ausführlicher als notwendig, kann aber in Situationen hilfreich sein, in denen Sie mehreren Objektprototypen die gleiche Methode zuweisen möchten.

Frage: Ist "Foo" im Beispiel ein Objekt, oder ist es ein Namensraum? Warum ist das Google-Beispiel nicht der folgende Code (der nicht funktioniert): prototype.bar = function() { ... };

  1. Foo ist ein Objekt. Obwohl das Konzept durch die Verwendung von statischen Objekten ausgedrückt werden kann, wie ich in gezeigt habe meine Antwort auf deine andere FrageEs gibt keine Namespaces in JavaScript. Weiterhin, insbesondere in dem angegebenen Beispielcode, Foo ist wahrscheinlich ein instanziiertes Objekt, das verhindert, dass es sich wie ein Namespace verhält.

  2. Natürlich funktioniert es nicht: prototype wurde nicht als Objekt definiert (es sei denn, Sie definieren es als solches). Das prototype  Eigentum existiert auf jedem Objekt (eine Funktion ist auch ein Objekt), weshalb Sie tun können Foo.prototype.bar = ...;. Lesen  Mehr  Hier.


7
2017-07-18 07:57



=====> 2017 Update <=====

Diese Frage und Antworten ist 7 Jahre alt und ist sehr veraltet. Diese Antwort enthält eine neue Syntax für Versionen von ES5, ES6und kompatibel mit ES7.


Der beste Weg, um eine Funktion zu definieren?

Es gibt keine "beste" Möglichkeit, eine Funktion zu definieren. Wie Sie die Funktion definieren, hängt von der beabsichtigten Verwendung und der Lebensdauer der Funktion ab.

Globale Funktionen

Definiert als eine Anweisung mit dem Funktionstoken gefolgt von dem Funktionsnamen mit Camelcase in Kleinbuchstaben

function functionName (arguments) {
    // function body
}

ist vorzuziehen gegenüber dem Funktionsausdruck ...

var functionName = function (arguments) {
     // function body
}

... da die Zuweisung an die Variable der Funktion erst erfolgt, wenn die definierende Zeile ausgeführt wird. Im Gegensatz zur bevorzugten Methode, die unmittelbar nach dem Parsen verfügbar ist, bevor ein Code ausgeführt wird.

const functionName = function(arguments){/*function body*/}
var functionName = function functionName(arguments){/*function body*/}
var functionName = function functionAltName(arguments){/*function body*/}

Funktionsobjekte

Als eine Funktionsanweisung mit Großbuchstaben Camelcase-Funktionsname

function MyObjectFunction (arguments) {
    /*function body*/
    // if this function is called with the new token
    // then it exits with the equivalent return this;
}

const obj = new MyObjectFunction(foo);

Anonymer Funktionsausdruck.

Eine gängige Praxis besteht darin, ein Objekt über eine sofort aufgerufene Funktion zu erstellen, die keinen Namen hat (und daher anonym ist).

;(function (arguments) { /*function body*/ } ("argument val"))

Oder

;(function(arguments){ /*function body*/ })("argument val")

HINWEIS die Einbeziehung der ; vor der Funktion. Dies ist sehr wichtig, da das offene "(") verhindert, dass automatisch ein Semikolon in einen Code oberhalb der Funktion eingefügt wird.

Sofort aufgerufener Funktionsausdruck.

const functionResult = (function (arguments) {
      /*function body*/
      return functionResult;
}());

const functionResult = (function (arguments) {
      /*function body*/
      return functionResult;
})();

Als ein var oder Blockbereichconst, let

Anonymer Rückruf

Bei ES6 sollten Sie die Pfeilfunktionssyntax anstelle von anonymen Funktionsausdrücken verwenden.

 myArray.forEach((item,i) => {/*function body*/});
 myArray.filter(item => !item);
 setTimeout(() => {/*function body*/}, 1000);

Funktion als Eigenschaften.

Verwenden der Kurzschreibesyntax der Objektdeklarationsfunktion.

var myObj = {
    functionName (arguments) {/*function body*/},
}

// called 
myObj.functionName("arg");

ist vorzuziehen

var myObj = {
    functionName : function (arguments) {/*function body*/},
}

Oder über Funktionsobjektdeklarationen

function MyObjectFunction(arguments){
     this.propertyFunction = function(arguments) { /*function body*/ }
     // or arrow notation is fine
     this.propertyFunction = (argument) => { /*function body*/ };
}

Funktioniert als Prototyp

function MyObj (arguments) {
      MyObj.prototype.functionName = function(arguments) { /*function body*/ }
}

oder

function MyObj (arguments) {}
MyObj.prototype.functionName = function(arguments) { /*function body*/ }

oder

MyObj.prototype = {
    functionName(arguments) { /*function body*/ }
}

3
2018-02-27 13:15



Das Definieren einer Prototypfunktion ist nützlich, wenn Sie Konstruktoren oder "Klassen" in JavaScript erstellen. z.B. eine Funktion, die du willst new

var MyClass = function(){};
MyClass.prototype.doFoo = function(arg){ bar(arg); }

aber in einfachen alten Bibliotheksfunktionen, z.B.

function doPopup(message){ /* create popup */};

Es gibt mehrere Vorteile der Verwendung einer Prototypfunktion, einschließlich, aber nicht beschränkt auf

  • Geschwindigkeit
  • Speichernutzung
  • Erweiterbarkeit

Aber auch dies ist im Kontext der Erstellung von Konstruktoren für instanziierbare 'Klassen'

HTH


2
2017-07-18 03:54



Es funktioniert so:

(function(){ // create an isolated scope
    // My Object we created directly
    var myObject = {
        a: function(x,y) {
            console.log('a');
        },
        b: function(x,y) {
            console.log('b');
            this.a(x,y);
        }
    };
})();

(function(){ // create an isolated scope

    // Create a Object by using a Class + Constructor
    var myClass = function(x,y) {
        console.log('myClass: constructor');
        this.b(x,y);
    };
    myClass.prototype = {
        a: function(x,y) {
            console.log('myClass: a');
        },
        b: function(x,y) {
            console.log('myClass: b');
            this.a(x,y);
        }
    };

    // Define a function that should never inherit
    myClass.c = function(x,y) {
        console.log('myClass: c');
        this.a(x,y);
    };

    // Create Object from Class
    var myObject = new myClass();
    // Will output:
    // myClass: constructor
    // myClass: b
    // myClass: a

    // Define a function that should never inherit
    myObject.d = function(x,y) {
        console.log('myObject: d');
        this.a(x,y);
    };

    // Test the world is roung
    console.log(typeof myClass.c, 'should be undefined...');
    console.log(typeof myClass.d, 'should be function...');
})();

(function(){ // create an isolated scope
    // If you are using a framework like jQuery, you can obtain inheritance like so

    // Create a Object by using a Class + Constructor
    var myClass = function(x,y) {
        console.log('myClass: constructor');
        this.b(x,y);
    };
    myClass.prototype = {
        a: function(x,y) {
            console.log('myClass: a');
        },
        b: function(x,y) {
            console.log('myClass: b');
            this.a(x,y);
        }
    };

    // Create new Class that inherits
    var myOtherClass = function(x,y) {
        console.log('myOtherClass: constructor');
        this.b(x,y);
    };
    $.extend(myOtherClass.prototype, myClass.prototype, {
        b: function(x,y) {
            console.log('myOtherClass: b');
            this.a(x,y);
        }
    });

    // Create Object from Class
    var myOtherObject = new myOtherClass();
    // Will output:
    // myOtherClass: constructor
    // myOtherClass: b
    // myClass: a
})();

(function(){ // create an isolated scope
    // Prototypes are useful for extending existing classes for the future
    // Such that you can add methods and variables to say the String class
    // To obtain more functionality
    String.prototype.alert = function(){
        alert(this);
    };
    "Hello, this will be alerted.".alert();
    // Will alert:
    // Hello, this will be alerted.
})();

Edit: Code korrigiert, so dass es beim Kopieren und Einfügen tatsächlich in deinem Browser läuft :-)


1
2017-07-18 03:54



Foo ist sowohl ein Objekt als auch ein Namensraum. Sehen diese Frage.

Die Verwendung von Objekten als Namespaces verhindert Namenskonflikte. Das ist immer eine gute Idee, besonders wenn Sie Shared Libraries entwickeln und / oder verwenden.

Wenn Sie nicht erwarten, mehrere Foo-Objekte zu erstellen (und somit den objektorientierten Stil nicht benötigen), könnten Sie Ihre Funktionen als Methoden für ein Singleton-Objekt erstellen:

var Foo = {}
Foo.bar = function() { ... }

oder

var Foo = {
    bar: function() {...},
    quux: function() {...}
};

Sie würden dann die Funktion einfach wie folgt aufrufen:

Foo.bar()

(Diese Deklaration entspricht in etwa einer statischen Methode in C ++ oder Java.)


0
2017-07-18 03:55