it-swarm.com.de

Was ist die empfohlene Methode zum Erstellen von Objekten in NodeJS?

Ich baue ein Composite für request-Modul. Ich bin mir jedoch nicht sicher, was die beste Vorgehensweise beim Erstellen von Objekten in JS for Node ist.

Option 1:

function RequestComposite(request) {
  return {
    get: function (url) { return request.get(url); }
  }
}
var comp = RequestComposite(request);
  • Hinweis: Ich weiß, dass ich eine CB auf asynchrone Weise anrufen sollte, aber zur Vereinfachung der Erklärung gebe ich sie zurück ...

Option 2:

function RequestComposite(request) {
  this.request = request;
}

RequestComposite.prototype.get = function (url) { return this.request.get(url); };
var comp = new RequestComposite(request);

Option 3:

var RequestComposite = {
  init: function (request) { this.request = request; },
  get: function (url) { return request.get(url); }
}
var comp = Object.create(RequestComposite).init(request);

Ich versuchte mich zu orientieren, wurde jedoch noch verwirrter darüber, wie ich Objekte benutzen sollte ...

Wäre die Antwort anders, wenn ich Objekte für Browser verwenden möchte?

Vielen Dank.

29
tounano

Der effizienteste Weg ist der folgende:

  • Legen Sie im Konstruktor nur Eigenschaften fest.

  • Legen Sie Methoden in der .prototype-Eigenschaft des Konstruktors fest. Warum? Dies verhindert, dass jede Methode jedes Mal neu geschrieben wird, wenn Sie ein Objekt erstellen. Auf diese Weise recyceln Sie für jedes von Ihnen erstellte Objekt denselben Prototyp. Effizient im Gedächtnis und in der Zeit.

  • Verwenden Sie keine Verschlüsse für private Immobilien. Warum ?: Es ist langsam und verhindert, dass Sie dieses Objekt in einer Vererbungskette verwenden (die pseudo-privaten Variablen gehören nicht zum Objekt, sie sind nur zugänglich). Verwenden Sie stattdessen einen Unterstrich, um anzugeben, dass es sich um eine private Eigenschaft handelt, auf die nicht von außen zugegriffen werden darf.

  • Verwenden Sie new anstelle von Object.create. Es ist schneller und am Ende verwendet Object.create new unter der Haube.

Mit anderen Worten, so etwas:

var Person = function (name) {
    this._name = name;
};

Person.prototype.sayHello = function () {
    alert('My name is: ' + this._name);
};

var john = new Person('John');
john.sayHello();

BEARBEITEN

Einige zusätzliche Informationen:

  • Object.create vs new. Benchmark hier . Obwohl die Frage für node.js ist, denke ich, dass das gleiche Verhalten zu erwarten ist. (jede Korrektur ist willkommen)

  • Verschlüsse, um private Eigenschaften zu emulieren: In dieser Frage können Sie über lesen. . Der Punkt, dass die privaten/schließenden Eigenschaften nicht zum Objekt gehören, ist ein Programmierfaktor: Sie sind für die Objektmethoden zugänglich, jedoch nicht zum Objekt. Bei der Vererbung ist das ein großes Durcheinander. Außerdem haben nur die im Konstruktor deklarierten Methoden Zugriff auf die Schließung. Im Prototyp definierte Methoden nicht.

  • Definieren von Methoden im Konstruktor oder in der Prototypeneigenschaft: Lesen Sie diese Frage , und werfen Sie einen Blick auf diesen Benchmark

EDIT 15/04/2016

Die Punkte, die ich vor drei Jahren hier gemacht habe, sind aus Sicht der Leistung immer noch richtig, aber meine Meinung, was der "empfohlene Weg" ist, hat sich in der Zwischenzeit etwas geändert. Werksfunktionen sind im Allgemeinen eine gute Option. Dies wäre der erste Ansatz des OP. Nur ein Beispiel:

function Person(name) {
    return {
        sayHello: function () { alert('My name is: ' + name); }
    };
}

und dann einfach:

var p = Person('John');

In diesem Fall tauschen Sie Flexibilität (keine new-Kopplung, einfache Komposition mit anderen "Mix-Ins") und Einfachheit (kein this-Chaos, einfache Objektinstanzierung) gegen Geschwindigkeit und Speicherplatz aus. Im Allgemeinen sind sie vollkommen gültig. Wenn Sie Leistungsprobleme haben, die auf diese Art der Erstellung von Objekten zurückzuführen sind, kehren Sie zu einer anderen Methode zurück. Der Object.create-Ansatz ist ebenfalls gut und fällt irgendwie in die Mitte von new- und Factory-Funktionen (Anmerkung: Die neue class-Syntax ist syntaktischer Zucker für new + prototype)

Zusammenfassend: Mein empfohlener Weg ist der einfachste und einfachste Weg, Objekte zu erstellen (Factory-Funktionen), und dann auf andere Methoden zu stoßen, wenn Sie auf Leistungsprobleme stoßen (was in den meisten Fällen niemals der Fall ist).

45
bgusach

Es gibt viele Möglichkeiten, "Class" und "Object" in JS zu erstellen. Ich bevorzuge diesen Weg:

var MyObject =
        function(args) {
            // Private
            var help = "/php/index.php?method=getHelp";
            var schedule = "/php/index.php?method=getSchedules";
            var ajax = function(url, callback, type) {
                //....
            }

            // Public
            this.property = 0;
            this.getInfo = function() {
                // ... 
            }

            // Constructor
            function(data) {
               this.property = data;
           }(args);
        };

var o = new MyObject();
7
ovnia

Hinweis: Wenn Sie mit der Syntax von OOP besser vertraut sind, können Sie auch class verwenden. Dies ist lediglich syntaktischer Zucker über vorhandene Prototypen.

Leistungsvergleich zwischen 4 Arten der Objekterstellung - mit Konstruktor (Chrome 61 - https://jsperf.com/create-object-ways )

Option A: Verwenden von return (schnellste 3x)

Option B: Verwenden von {key:value} (1.5x)

Option C: Verwendung von prototype (1x) <- Base

Option D: Verwenden von class (1.02x)

Option A Nähte, um die besten Ergebnisse zu erzielen. Beachten Sie, dass einige der Leistungssteigerungen darauf zurückzuführen sind, dass new oder object.create nicht verwendet werden. Um nur einen fairen Versuch zu haben, ist hier ein weiterer Test zwischen Nur-Methoden-Objekten ohne Konstruktor und Eigenschaften.


Leistungsvergleich zwischen 4 Methoden zum Erstellen von Methodenobjekten (Chrome 61 - https://jsperf.com/create-static-object-ways )

Option A: Verwenden von return (3.2x)

Option B: Verwenden von {key:value} (schnellste 3.3x)

Option C: Verwenden von prototype (1.8x)

Option D: Verwenden von class (1.9x)

Option B hat Option A etwas übertroffen. Auch der durch object.create verursachte Engpass war mehr als new.


Beste Übung

Option A (mit return) bietet in beiden Szenarien die beste Leistung. Dieser Weg kann etwas unordentlich werden, wenn Sie viele Methoden und Eigenschaften haben.

Ich bevorzuge es, Konstruktor und Eigenschaften in separaten Objekten mit Option A und Methoden in einem anderen Objekt mit Option B aufzuteilen. Dieser Ansatz muss eine zusätzliche instance-Referenz in Parametern senden, kann jedoch nützlich sein, wenn Sie mehrere Objekte mit denselben Eigenschaften und Konstruktor haben (einige OOP - Vererbung kann auch erreicht werden).

Beispiel:

// Constructor & Properties Object (Using option A)
var UserData = function(request){

  // Constructor
  if ( request.name )
    var name = request.name;
  else
    var name = 'Not Available';

  if ( request.age )
    var age = request.age;
  else
    var age = null;


  // Return properties
  return {
    userName: name,
    userAge: age
  };

};


// Object methods (Using Option B)
var Adults = {

  printName: function(instance){ // Read propery example
    console.log( 'Mr. ' + instance.userName );
  },

  changeName: function(instance, newName){ // Write property example
    instance.userName = newName;
  },

  foo: function(){
    console.log( 'foo' );
  }

};


// Object methods (Using Option B)
var Children = {

  printName: function(instance){
    console.log( 'Master ' + instance.userName );
  },

  bar: function(){
    console.log( 'bar' );
  }

}


// Initialize
var userData = UserData ( {name: 'Doe', age: 40} );

// Call methods
Adults.printName(userData); // Output 'Mr. Doe'
Children.printName(userData); // Output 'Master Doe'

Adults.foo(); // Output 'foo'
Children.bar(); // Output 'bar'

Adults.changeName(userData, 'John');
Adults.printName(userData); // Output 'Mr. John'
1
SJ00