Sollte ich Objektliterale oder Konstruktorfunktionen verwenden?

94

Ich bin verwirrt darüber, auf welche Weise ich ein Objekt in Javascript erstellen soll. Es scheint, dass es mindestens zwei Möglichkeiten gibt. Eine besteht darin, die Objektliteralnotation zu verwenden, während die andere Konstruktionsfunktionen verwendet. Gibt es einen Vorteil gegenüber dem anderen?

Chobo
quelle
1
Die beste Antwort: stackoverflow.com/questions/4597926/… - Zusammenfassend können Sie eine Funktion einrichten, um Instanzen auch in Literalschreibweise zu erstellen. Dabei enthält jede Instanz alle Methoden, während bei einem Konstruktor alle Instanzen auf die Prototypmethoden verweisen. Dh der Konstruktor hat eine bessere Speicherleistung.
Federico
Wenn der Speicher kein Problem darstellt, ist der Zugriff auf Objektliterale um viele Größenordnungen schneller - jsperf.com/module-pattern-vs-object-literal-vs-prototype/4
Daniel Sokolowski

Antworten:

131

Wenn Sie kein Verhalten mit einem Objekt verknüpft haben (dh wenn das Objekt nur ein Container für Daten / Status ist), würde ich ein Objektliteral verwenden.

var data = {
    foo: 42,
    bar: 43
};

Wenden Sie das KISS-Prinzip an . Wenn Sie nichts anderes als einen einfachen Datencontainer benötigen, verwenden Sie ein einfaches Literal.

Wenn Sie Ihrem Objekt Verhalten hinzufügen möchten, können Sie mit einem Konstruktor dem Objekt während der Erstellung Methoden hinzufügen oder Ihrer Klasse einen Prototyp geben.

function MyData(foo, bar) {
    this.foo = foo;
    this.bar = bar;

    this.verify = function () {
        return this.foo === this.bar;
    };
}

// or:
MyData.prototype.verify = function () {
    return this.foo === this.bar;
};

Eine Klasse wie diese verhält sich auch wie ein Schema für Ihr Datenobjekt: Sie haben jetzt eine Art Vertrag (über den Konstruktor), welche Eigenschaften das Objekt initialisiert / enthält. Ein freies Literal ist nur ein amorpher Datenklumpen.

Sie können auch eine externe verifyFunktion haben, die auf ein einfaches altes Datenobjekt wirkt:

var data = {
    foo: 42,
    bar: 43
};

function verify(data) {
    return data.foo === data.bar;
}

Dies ist jedoch im Hinblick auf die Kapselung nicht günstig: Idealerweise sollten alle Daten + Verhaltensweisen, die mit einer Entität verbunden sind, zusammenleben.

Ates Goral
quelle
12
Gute Erklärung, aber was ist mit dem Einfügen von Funktionen in ein Objektliteral? Ich habe das schon einmal gesehen. Eigentlich hat der Beitrag unten ein Beispiel dafür.
Chobo
23
Wenn Sie die Funktionsdefinitionen als Teil des Objektliteral einfügen oder den this.fn = function ...Ansatz in einem Konstruktor verwenden, verfügt jede Ihrer Objektinstanzen über eigene Kopien von Funktionen. Mit dem Prototyp-Ansatz hängen Sie jede Funktion einmal und nur einmal an: Sie werden von den Instanzen durch prototypische Vererbung vererbt.
Ates Goral
14
Ich glaube, Sie haben eine wichtige Sache verpasst. Nur die Konstruktorfunktion kann sowohl private als auch öffentliche Mitglieder bereitstellen (Kapselung). im Objektliteral - sie sind alle öffentlich.
Royi Namir
Was wäre ein besserer Weg für eine Spiel-Engine? Ich habe die Konstruktormethode verwendet, aber meine Prototypen haben keinen Zugriff auf die Konstruktordaten.
Zachdyer
90

Es läuft im Wesentlichen darauf hinaus, ob Sie mehrere Instanzen Ihres Objekts benötigen oder nicht. Mit einem mit einem Konstruktor definierten Objekt können Sie mehrere Instanzen dieses Objekts haben. Objektliterale sind im Grunde Singletons mit Variablen / Methoden, die alle öffentlich sind.

// define the objects:
var objLit = {
  x: 0,
  y: 0,
  z: 0,
  add: function () {
    return this.x + this.y + this.z;
  }
};

var ObjCon = function(_x, _y, _z) {
  var x = _x; // private
  var y = _y; // private
  this.z = _z; // public
  this.add = function () {
    return x + y + this.z; // note x, y doesn't need this.
  };
};

// use the objects:
objLit.x = 3; 
objLit.y = 2; 
objLit.z = 1; 
console.log(objLit.add());    

var objConIntance = new ObjCon(5,4,3); // instantiate an objCon
console.log(objConIntance.add());
console.log((new ObjCon(7,8,9)).add()); // another instance of objCon
console.log(objConIntance.add()); // same result, not affected by previous line
Ronnbot
quelle
1
Dies ist ein sehr guter Punkt, den Sie bei der Entscheidung berücksichtigen sollten. Vielen Dank.
zkent
Nach meiner Erfahrung macht genau das den Unterschied. Tolles klares Beispiel.
Air
9

Eine andere Möglichkeit, Objekte auf einheitliche Weise zu erstellen, besteht darin, eine Funktion zu verwenden, die ein Objekt zurückgibt:

function makeObject() {
    var that = {
        thisIsPublic: "a public variable"
        thisIsAlsoPublic: function () {
            alert(that.thisIsPublic);
        }
    };

    var secret = "this is a private variable"

    function secretFunction() { // private method
        secret += "!"; // can manipulate private variables
        that.thisIsPublic = "foo";     
    }

    that.publicMethod = function () {
        secret += "?"; // this method can also mess with private variables
    }

    that.anotherPublicVariable = "baz";

    return that; // this is the object we've constructed
}

makeObject.static = "This can be used to add a static varaible/method";

var bar = makeObject();
bar.publicMethod(); // ok
alert(bar.thisIsPublic); // ok
bar.secretFunction(); // error!
bar.secret // error!

Da Funktionen in JavaScript Abschlüsse sind, können wir private Variablen und Methoden verwenden und vermeiden new.

Von http://javascript.crockford.com/private.html zu privaten Variablen in JavaScript.

JustcallmeDrago
quelle
7

Der folgende Code zeigt drei Methoden zum Erstellen eines Objekts: die Objektliteral-Syntax, einen Funktionskonstruktor und Object.create(). Die Objektliteral-Syntax erstellt und objektiert einfach im laufenden Betrieb. Als solches __prototype__ist es das ObjectObjekt und hat Zugriff auf alle Eigenschaften und Methoden von Object. Aus Sicht des Entwurfsmusters sollte ein einfaches Objektliteral verwendet werden, um eine einzelne Dateninstanz zu speichern.

Der Funktionskonstruktor hat eine spezielle Eigenschaft namens .prototype. Diese Eigenschaft wird zu __prototype__allen Objekten, die vom Funktionskonstruktor erstellt wurden. Alle Eigenschaften und Methoden, die der .prototypeEigenschaft eines Funktionskonstruktors hinzugefügt wurden, stehen allen von ihm erstellten Objekten zur Verfügung. Ein Konstruktor sollte verwendet werden, wenn Sie mehrere Instanzen der Daten benötigen oder Verhalten von Ihrem Objekt benötigen. Beachten Sie, dass der Funktionskonstruktor auch am besten verwendet wird, wenn Sie ein privates / öffentliches Entwicklungsmuster simulieren möchten. Denken Sie daran, alle gemeinsam genutzten Methoden auf zu setzen, .prototypedamit sie nicht in jeder Objektinstanz erstellt werden.

Beim Erstellen von Objekten mit wird Object.create()ein Objektliteral als __prototype__für die mit dieser Methode erstellten Objekte verwendet. Alle Eigenschaften und Methoden, die dem Objektliteral hinzugefügt wurden, stehen allen Objekten zur Verfügung, die durch echte prototypische Vererbung daraus erstellt wurden. Dies ist meine bevorzugte Methode.

//Object Example

//Simple Object Literal
var mySimpleObj = {
    prop1 : "value",
    prop2 : "value"
}

// Function Constructor
function PersonObjConstr()  {
    var privateProp = "this is private";
    this.firstname = "John";
    this.lastname = "Doe";
}
PersonObjConstr.prototype.greetFullName = function()    {
    return "PersonObjConstr says: Hello " + this.firstname + 
    " " + this.lastname;
};

// Object Literal
var personObjLit = {
    firstname : "John",
    lastname: "Doe",
    greetFullName : function() {
        return "personObjLit says: Hello " + this.firstname +
        ", " + this.lastname;
    }
} 

var newVar = mySimpleObj.prop1;
var newName = new PersonObjConstr();
var newName2 = Object.create(personObjLit);
JOP
quelle
1
Da Sie die Funktion in einem Objektliteral deklariert haben. Bedeutet das, dass beim Erstellen eines Objekts mit Object.createder Funktion im Literal die Instanz eindeutig ist?
JohnnyQ
6

Es hängt davon ab, was Sie tun möchten. Wenn Sie (halb-) private Variablen oder Funktionen in Ihrem Objekt verwenden möchten, können Sie dies mit einer Konstruktorfunktion tun. Wenn Ihr Objekt nur Eigenschaften und Methoden enthält, ist ein Objektliteral in Ordnung.

function SomeConstructor(){
    var x = 5;
    this.multiply5 = function(i){
        return x*i;
    }
}
var myObj = new SomeConstructor;

var SomeLiteral = {
    multiply5: function(i){ return i*5; }
}

Nun ist die Methode multiply5in myObjund SomeLiteralmacht genau das Gleiche. Der einzige Unterschied besteht darin, dass myObj eine private Variable verwendet. Letzteres kann in einigen Fällen nützlich sein. In den meisten Fällen ist ein Objektliteral ausreichend und eine schöne und saubere Möglichkeit, ein JS-Objekt zu erstellen.

KooiInc
quelle
Was ist der Unterschied zwischen einer Funktion und einer Methode? Ich komme aus einem ac # -Hintergrund, daher ist eine Funktion für mich eigenständig und eine Methode ist nur eine Funktion, die Teil einer Klasse ist.
Chobo
1
Es gibt nicht so viel Unterschied, siehe zum Beispiel web-source.net/javascript_tutorial/… . Tatsächlich werden in DOMscripting (clientseitige js in einem Browser) alle Funktionen zu Methoden des Fensterobjekts (des globalen Namespace), würde ich sagen (Sie können alle 'eigenständigen' Funktionen als Fenster adressieren. [Irgendeine Funktion].
KooiInc
5

Geben Sie hier die Bildbeschreibung ein

Möchten Sie eine einzelne Instanz des Objekts für die Seite - Literal.

Möchten Sie nur Daten wie DTO-Objekte einfach übertragen? GET SET: - Literal

Möchten Sie reale Objekte mit Methodenverhalten, mehreren Instanzen erstellen - Konstruktorfunktion, Befolgen Sie die OOP-Prinzipien, Vererbung: - Konstruktorfunktionen.

Unten sehen Sie das Youtube-Video, in dem ausführlich erklärt wird, was wörtlich ist, was Konstruktorfunktionen sind und wie sie sich voneinander unterscheiden.

https://www.youtube.com/watch?v=dVoAq2D3n44

Shivprasad Koirala
quelle
1

Gehen Sie mit Objektliteral, es ist konsistenter und erweitert sich besser mit der Einführung von Anfangswerten.

Tom
quelle
Wie erstellen Sie private Variablen in einem Objektliteral?
EhevuTov
Sie können nicht wirklich, es ist nicht relevant für die ursprüngliche Frage, also werde ich Ihnen nur einen Link geben: javascript.crockford.com/private.html
Tom
1
Tatsächlich ist es relevant, denn wo es einen Unterschied gibt, gibt es einen Grund, je nach bestimmten Situationen den einen oder anderen zu verwenden. In diesem Fall ist es, ob Sie private Variablen möchten oder nicht. Sie können private Variablen in einem Literal erstellen, indem Sie zuerst eine Abschlussfunktion in Ihrem Literal erstellen, aber meiner Meinung nach ist sie viel hässlicher und schwer zu lesen.
EhevuTov
Ich stehe korrigiert da. Meine ursprüngliche Lesart der Frage war, dass Chobo fragte, wie Variablen an einen Konstruktor übergeben werden sollen, wie in der Parameterliste im Vergleich zu einzelnen Objektliteralparametern.
Tom
1

Wie unter https://www.w3schools.com/js/js_object_definition.asp erwähnt

Mit Hilfe eines Objektliteral, sowohl Sie definieren und erstellen , ein Objekt in einer Erklärung.

Ebenfalls

Objektliteral erstellt nur ein einzelnes Objekt. Manchmal möchten wir einen Objekttyp haben , mit dem viele Objekte eines Typs erstellt werden können.

Alireza Fattahi
quelle
0

Die Object () -Konstruktorfunktion ist etwas langsamer und ausführlicher. Daher wird empfohlen, neue Objekte in JavaScript zu erstellen, indem Sie die Literalschreibweise verwenden

Udacity Objektorientiertes JavaScript

techkuz
quelle
0

Eigentlich können wir private Methoden in Objektliteralen haben. Betrachten Sie den folgenden Code:

var myObject = {

   publicMethod: function () {
      privateMethod1();
      privateMethod2(); 
      function privateMethod1(){
          console.log('i am privateMethod1');
      } 
      function privateMethod2(){
          console.log('i am privateMethod2');
      } 
   }

}

Geschmackssache, aber ich bevorzuge Objektliterale, wo es möglich ist.

Yurin
quelle
-1

// Objektliteral und Objektkonstruktor

function MyData(foo, bar) {
        this.foo = foo;
        this.bar = bar;

    }
MyData.prototype.verify = function () {
        return this.foo === this.bar;
    };

//add property using prototype

var MD  = new MyData;//true.
var MD = new MyData();//true.
MD.verify// return only the function structure.
MD.verify(); //return the verify value and in this case return true coz both value is null. 
var MD1  = new MyData(1,2); // intialized the value at the starting. 
MD1.verify// return only the function structure.
MD1.verify(); // return false coz both value are not same.
MD1.verify(3,3);// return false coz this will not check this value intialized at the top 
MyData.prototype.verify = function (foo,bar) {
    return this.foo === this.bar;
};
var MD1  = new MyData(1,2);
MD1.verify();
MD1.verify(3,3);// return false coz this keyword used with foo and bar that will check parent data 
Amit Kumar
quelle
1
Wo in Ihrem Beispiel wird das Objektliteral deklariert?
JohnnyQ