Was ist der Unterschied zwischen "new Object ()" und der Objektliteralnotation?

199

Was ist der Unterschied zwischen dieser konstruktorbasierten Syntax zum Erstellen eines Objekts:

person = new Object()

... und diese wörtliche Syntax:

person = {
    property1 : "Hello"
};

Es scheint, dass beide dasselbe tun, obwohl JSLint die Verwendung der Objektliteralnotation bevorzugt.

Welches ist besser und warum?

ectype
quelle
7
Alle gleich: a = new Object, a = new Object(), a = {}ist, wörtliche viel einfacher und einige Tests ich lief vor einiger Zeit sagen , dass es schneller ist, neuerer Compiler meiner Aussage falsch sein verursacht haben könnte. Gleiches gilt für wörtliche Arrays
Juan Mendes
8
Hoffentlich deklarieren Sie Ihre Variablen mit dem varSchlüsselwort in Ihrem Anwendungscode, um eine Verschmutzung des globalen Namespace und die Notwendigkeit zu vermeiden, über den aktuellen Datensatz im Stapel hinaus nach Ihren Variablen zu suchen.
Samo
1
Grundsätzlich gibt es zu jedem Zeitpunkt während der Ausführung eines Programms einen Stapel von Datensätzen oder Blöcken. Jeder Datensatz enthält eine Liste von Variablen, die in diesem Bereich erstellt wurden. Wenn ein Ausdruck in JavaScript eine Variable enthält und der Interpreter sie im Stapeldatensatz für diesen Bereich nicht finden kann, wird er mit dem nächsten Datensatz fortfahren, bis er die Variable findet. Weitere Informationen davidshariff.com/blog/…
Samo
2
Das Vermeiden von JSLint ist der erste Schritt, um ein guter Entwickler zu werden. Die Verwendung newist eine Konvention, die über die sinnlose Auswahl einer mittelmäßigen Sprache hinausgeht. Verwenden Sie, newweil seine Bedeutung klar ist. In 99,9% der Fälle sind die Leistungssteigerungen irrelevant.
Hal50000
1
@ Hal50000 mittelmäßige Sprache nach wem?
Xam

Antworten:

124

Beide machen dasselbe (es sei denn, jemand hat etwas Ungewöhnliches getan), außer dass Ihr zweites Objekt erstellt und ihm eine Eigenschaft hinzufügt. Die Literalschreibweise benötigt jedoch weniger Platz im Quellcode. Es ist klar erkennbar, was gerade passiert. new Object()Wenn Sie also verwenden , tippen Sie wirklich nur mehr und führen (theoretisch, wenn nicht durch die JavaScript-Engine optimiert) einen unnötigen Funktionsaufruf durch.

Diese

person = new Object() /*You should put a semicolon here too.  
It's not required, but it is good practice.*/ 
-or-

person = {
    property1 : "Hello"
};

technisch nicht das gleiche tun. Der erste erstellt nur ein Objekt. Der zweite erstellt eine und weist eine Eigenschaft zu. Damit der erste identisch ist, benötigen Sie einen zweiten Schritt, um die Eigenschaft zu erstellen und zuzuweisen.

Das "Ungewöhnliche", das jemand tun könnte, wäre, den Standard Objectglobal zu beschatten oder zuzuweisen :

// Don't do this
Object = 23;

In diesem höchst ungewöhnlichen Fall new Objectwird aber scheitern{} wird funktionieren.

In der Praxis gibt es nie einen Grund, new Objectanstatt zu verwenden {}(es sei denn, Sie haben diese sehr ungewöhnliche Sache getan).

kemiller2002
quelle
11
Der Autor hat diese Antwort als richtig gewählt, sie ist jedoch unvollständig. Beachten Sie, dass es Unterschiede zwischen den beiden Syntaxen gibt, wenn Sie mit der Speicherzuweisung beginnen.
Newshorts
2
Es gibt keine Unterschiede. Wenn Sie sich auf eine der Antworten unter beziehen, handelt es sich nicht um ein Thema, da es sich um ein prototypbasiertes Objektmodell und eine Vererbung handelt (der dortige Code richtet eine Obj-Klasse ein, die von einem einfachen Objekt erbt). Bei dieser Frage geht es nicht darum, eine Instanz einer benutzerdefinierten Klasse zu erstellen, sondern darum, eine Instanz von Object zu erstellen. Die richtige Antwort auf diese Frage lautet "Es gibt keinen Unterschied".
Dos
FYI () new Object()ist auch nicht erforderlich. (spricht über nicht benötigtes Ding)
Royi Namir
Ich denke, wir müssen ab der aktuellen Spezifikation keine neuen verwenden . Lassen Sie mich Ihre Gedanken wissen @kevin
Vamsi Pavan Mahesh
1
Sie können auch Object create verwenden und null übergeben, wenn Sie ein Objekt möchten, das nicht von der Vererbungskette erbt. Sie sind nicht gleich und haben jeweils nützliche Zwecke.
Aaron
234

Für ein einfaches Objekt ohne Methoden wie in Ihrem Beispiel gibt es keinen Unterschied. Es gibt jedoch einen großen Unterschied, wenn Sie Ihrem Objekt Methoden hinzufügen.

Wörtlicher Weg:

function Obj( prop ) { 
    return { 
        p : prop, 
        sayHello : function(){ alert(this.p); }, 
    }; 
} 

Prototyp Weg:

function Obj( prop ) { 
    this.p = prop; 
} 
Obj.prototype.sayHello = function(){alert(this.p);}; 

In beiden Fällen können Instanzen Objwie diese erstellt werden:

var foo = new Obj( "hello" ); 

Mit der wörtlichen Methode tragen Sie jedoch eine Kopie der sayHelloMethode in jeder Instanz Ihrer Objekte. Während beim Prototyp die Methode im Objektprototyp definiert und von allen Objektinstanzen gemeinsam genutzt wird. Wenn Sie viele Objekte oder Methoden haben, kann der wörtliche Weg zu einer ziemlich großen Speicherverschwendung führen.

Rémy DAVID
quelle
39
Für mich ging es mehr um die Unterschiede zwischen der Verwendung von new Object()vs {}zum Erstellen leerer Objekte.
Peter
11
@Lobabob Abgesehen vom ersten Satz enthält diese Antwort keine Informationen über die Frage von OP. Es enthält nicht einmal 'new Object ()' irgendwo. Ehrlich gesagt denke ich, dass Herr David die Frage falsch verstanden hat.
JLRishe
17
Als ich dies gepostet habe, war die akzeptierte Antwort bereits da und wurde akzeptiert. Und es beantwortet perfekt die OP-Frage, sodass ich nicht dasselbe wiederholen wollte. Ich habe meine Antwort hauptsächlich veröffentlicht, um das Thema über leere / einfache Objekte hinaus zu erweitern. In diesem Fall gibt es einen wichtigen Unterschied, der erwähnenswert ist.
Rémy DAVID
3
Diese Antwort ist nicht zum Thema. In Ihrem Code ist Obj eine separate Klasse, die von Object erbt. Wenn Sie die Objektliteralnotation verwenden, verwenden Sie die Objektklasse und nicht Obj. Wenn Sie eine Klasse mit einer Methode in ihrem Prototyp einrichten, wird der Speicherbedarf natürlich kleiner als das Erstellen vieler einfacher Objekte und das Hinzufügen von Methoden als Eigenschaften, aber das hat nichts mit der hier gestellten Frage zu tun. Die richtige Antwort auf diese Frage lautet "Nein, es gibt absolut keinen Unterschied (vielleicht außer der Lesbarkeit)".
Dos
3
Ich kam für diese Antwort, basierend auf einer Frage, die meiner ähnlich war, aber am Ende genau lernte, was ich wissen musste. Danke dir.
Pat Migliaccio
55

In JavaScript können wir ein neues leeres Objekt auf zwei Arten deklarieren:

var obj1 = new Object();  
var obj2 = {};  

Ich habe nichts gefunden, was darauf hindeutet, dass es einen signifikanten Unterschied zwischen diesen beiden in Bezug auf ihre Funktionsweise hinter den Kulissen gibt (bitte korrigieren Sie mich, wenn ich falsch liege - ich würde es gerne wissen). Die zweite Methode (unter Verwendung der Objektliteralnotation) bietet jedoch einige Vorteile.

  1. Es ist kürzer (10 Zeichen um genau zu sein)
  2. Es ist einfacher und strukturierter, Objekte im laufenden Betrieb zu erstellen
  3. Es spielt keine Rolle, ob ein Trottel versehentlich ein Objekt überschrieben hat

Stellen Sie sich ein neues Objekt vor, das den Mitgliedsnamen und TelNo enthält. Mit der neuen Object () -Konvention können wir sie folgendermaßen erstellen:

var obj1 = new Object();  
obj1.Name = "A Person";  
obj1.TelNo = "12345"; 

Die Expando-Eigenschaften von JavaScript können wir auf diese Weise im neue Mitglieder erstellen und das erreichen, was beabsichtigt war. Dieser Weg ist jedoch nicht sehr strukturiert oder gekapselt. Was wäre, wenn wir die Mitglieder bei der Erstellung angeben wollten, ohne uns auf die Eigenschaften von expando und die Zuweisung nach der Erstellung verlassen zu müssen?

Hier kann die Objektliteralnotation helfen:

var obj1 = {Name:"A Person",TelNo="12345"};  

Hier haben wir den gleichen Effekt in einer Codezeile und deutlich weniger Zeichen erzielt.

Eine weitere Diskussion der oben genannten Objektkonstruktionsmethoden finden Sie unter: JavaScript und Object Oriented Programming (OOP).

Und schließlich, was ist mit dem Idioten, der Object außer Kraft gesetzt hat? Hast du gedacht, dass es nicht möglich ist? Nun, diese JSFiddle beweist das Gegenteil . Die Verwendung der Objekt-Literal-Notation verhindert, dass wir diesem Trottel verfallen.

(Von http://www.jameswiseman.com/blog/2011/01/19/jslint-messages-use-the-object-literal-notation/ )

James Wiseman
quelle
1
Wie wäre es mit Object.Create? Siehe: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Phil
Wenn Sie Objektliterale gegenüber bevorzugen, new Object()weil die Objektfunktion möglicherweise von etwas überschrieben wurde, sollten Sie auch überall Wachen schreiben, wenn Sie Helfer verwenden Object.keys, um sicherzustellen, dass sie nicht undefiniert sind, was zu Absurdität führt. Ich würde immer empfehlen, die wörtliche Notation zu verwenden, aber ich denke, dieses spezielle Argument fällt auseinander, wenn Sie über die Konsequenzen eines solchen Denkens nachdenken.
Philraj
41

Auf meinem Computer mit Node.js habe ich Folgendes ausgeführt:

console.log('Testing Array:');
console.time('using[]');
for(var i=0; i<200000000; i++){var arr = []};
console.timeEnd('using[]');

console.time('using new');
for(var i=0; i<200000000; i++){var arr = new Array};
console.timeEnd('using new');

console.log('Testing Object:');

console.time('using{}');
for(var i=0; i<200000000; i++){var obj = {}};
console.timeEnd('using{}');

console.time('using new');
for(var i=0; i<200000000; i++){var obj = new Object};
console.timeEnd('using new');

Beachten Sie, dass dies eine Erweiterung dessen ist, was hier zu finden ist: Warum ist arr = [] schneller als arr = new Array?

Meine Ausgabe war die folgende:

Testing Array:
using[]: 1091ms
using new: 2286ms
Testing Object:
using{}: 870ms
using new: 5637ms

{} und [] sind also eindeutig schneller als die Verwendung von new zum Erstellen leerer Objekte / Arrays.

rjloura
quelle
3
Ich denke, dies ist die Antwort, nach der die Frage wirklich gesucht hat, obwohl ich dies gerne zusätzlich an einem Objekt mit einigen Eigenschaften getestet hätte, um sicherzugehen.
Chase Sandmann
2
Interessante Zahlen. Es gibt Leute, die sich dessen bewusst sein müssen, aber ich nehme weg, dass das Zuweisen von nur mageren 200.000 Objekten mich nur 5,6 ms kostet, also werde ich mir darüber keine Sorgen machen.
Auf Knoten 10.13.0 haben sich die Dinge geändert Testarray: using []: 117.178ms using new: 116.947ms Testobjekt: using {}: 116.252ms using new: 115.910ms
PirateApp
31

Alle hier sprechen über die Ähnlichkeiten der beiden. Ich werde auf die Unterschiede hinweisen.

  1. Mit new Object()können Sie ein anderes Objekt übergeben. Das offensichtliche Ergebnis ist, dass das neu erstellte Objekt auf dieselbe Referenz gesetzt wird. Hier ist ein Beispielcode:

    var obj1 = new Object();
    obj1.a = 1;
    var obj2 = new Object(obj1);
    obj2.a // 1
  2. Die Verwendung ist nicht auf Objekte wie in OOP-Objekten beschränkt. Andere Typen könnten ebenfalls an ihn übergeben werden. Die Funktion stellt den Typ entsprechend ein. Wenn wir beispielsweise die Ganzzahl 1 übergeben, wird ein Objekt vom Typ Nummer für uns erstellt.

    var obj = new Object(1);
    typeof obj // "number"
  3. Das mit der obigen Methode ( new Object(1)) erstellte Objekt wird in den Objekttyp konvertiert, wenn ihm eine Eigenschaft hinzugefügt wird.

    var obj = new Object(1);
    typeof obj // "number"
    obj.a = 2;
    typeof obj // "object"
  4. Wenn das Objekt eine Kopie einer untergeordneten Objektklasse ist, können wir die Eigenschaft ohne die Typkonvertierung hinzufügen.

    var obj = new Object("foo");
    typeof obj // "object"
    obj === "foo" // true
    obj.a = 1;
    obj === "foo" // true
    obj.a // 1
    var str = "foo";
    str.a = 1;
    str.a // undefined
Jermin Bazazian
quelle
3
Ich bin sehr verwirrt über die letzten beiden Zeilen. Warum ist str.a undefiniert, wenn Sie str.a den Wert 1 zuweisen? @Jermin Bazazin
Andrea Scarafoni
3
@AndreaScarafoni, weil stres vom Typ ist, stringsodass Sie ihm keine Eigenschaft zuweisen können. jsfiddle.net/grq6hdx7/1
Chris Bier
1
Hat sich die Antwort auf 4 geändert? Ich werde falsch, nicht wahr, in der neuesten Chrome 53 var obj = new Object("foo"); typeof obj; obj === "foo" // true
William Hilton
21

Tatsächlich gibt es verschiedene Möglichkeiten, Objekte in JavaScript zu erstellen. Wenn Sie nur ein Objekt erstellen möchten, hat das Erstellen von " konstruktorbasierten " Objekten mit dem Operator " new " keinen Vorteil . Es ist dasselbe wie das Erstellen eines Objekts mit der Syntax " Objektliteral ". " Konstruktorbasierte " Objekte, die mit dem Operator " new " erstellt wurden, sind jedoch unglaublich nützlich, wenn Sie über " prototypische Vererbung " nachdenken . Sie können die Vererbungskette nicht mit Objekten verwalten, die mit Literal-Syntax erstellt wurden. Sie können jedoch eine Konstruktorfunktion erstellen , Eigenschaften und Methoden an den Prototyp anhängen."operator, gibt es ein Objekt zurück, das Zugriff auf alle Methoden und Eigenschaften hat, die mit dem Prototyp dieser Konstruktorfunktion verknüpft sind.

Hier ist ein Beispiel für das Erstellen eines Objekts mithilfe der Konstruktorfunktion (siehe Code-Erklärung unten):

function Person(firstname, lastname) {
    this.firstname = firstname;
    this.lastname = lastname;
}

Person.prototype.fullname = function() {
    console.log(this.firstname + ' ' + this.lastname);
}

var zubaer = new Person('Zubaer', 'Ahammed');
var john = new Person('John', 'Doe');

zubaer.fullname();
john.fullname();

Jetzt können Sie so viele Objekte erstellen, wie Sie möchten, indem Sie die Personenkonstruktionsfunktion instanziieren. Alle Objekte erben den vollständigen Namen () davon.

Hinweis: Das Schlüsselwort " this " bezieht sich auf ein leeres Objekt innerhalb einer Konstruktorfunktion. Wenn Sie mit dem Operator " new " ein neues Objekt aus Person erstellen , wird automatisch ein Objekt zurückgegeben, das alle Eigenschaften und Methoden enthält, die mit dem Schlüsselwort " this " verknüpft sind . Und diese Objekte erben mit Sicherheit die Methoden und Eigenschaften, die mit dem Prototyp der Person-Konstruktorfunktion verbunden sind (was der Hauptvorteil dieses Ansatzes ist).

Übrigens, wenn Sie die gleiche Funktionalität mit der " Objektliteral " -Syntax erhalten möchten, müssen Sie für alle Objekte wie folgt den vollständigen Namen () erstellen:

var zubaer = {
    firstname: 'Zubaer',
    lastname: 'Ahammed',
    fullname: function() {
        console.log(this.firstname + ' ' + this.lastname);
    }
};

var john= {
    firstname: 'John',
    lastname: 'Doe',
    fullname: function() {
        console.log(this.firstname + ' ' + this.lastname);
    }
};

zubaer.fullname();
john.fullname();

Wenn Sie jetzt fragen, warum ich den Konstruktorfunktionsansatz anstelle des Objektliteralansatzes verwenden soll :

*** Die prototypische Vererbung ermöglicht eine einfache Vererbungskette, die äußerst nützlich und leistungsfähig sein kann.

*** Es spart Speicher, indem allgemeine Methoden und Eigenschaften geerbt werden, die im Prototyp der Konstruktorfunktionen definiert sind. Andernfalls müssten Sie sie in allen Objekten immer wieder kopieren.

Ich hoffe das macht Sinn.

Md. Zubaer Ahammed
quelle
Vielen Dank! Karl für das Hinzufügen des fehlenden "dies" im Objektliteral. Es war ein schrecklicher Fehler. Ich hätte diese Art von Fehler nicht machen sollen.
Md. Zubaer Ahammed
"Sie können nicht von einem Objekt erben, das mit Literal-Syntax erstellt wurde." - Nicht wahr (glaube ich). Sie können nach Bedarf Vererbungsketten verwenden Object.create(<object defined using literal notation>)oder new Object(<object defined using literal notation>)erstellen.
Balajeerc
@balajeerc Danke für deinen Kommentar. Eigentlich sollte es "Sie können die Vererbungskette mit Objekten, die mit Literal-Syntax erstellt wurden, nicht verwalten" sein. Die Antwort erfolgt in mehreren Schritten: 1. Object.create (): Ja, es ist möglich, ein Objektliteral an dieses zu übergeben, und es wird ein neues Objekt zurückgegeben, dessen Prototyp das übergebene Objektliteral ist. Aber es weiß nicht, was es ist, ist Konstruktorfunktion oder erinnert sich nicht an das Objektliteral, aus dem es erstellt wurde. Testobj1.constructor gibt also eine leere Funktion zurück und es gibt keine Möglichkeit, diesem Objektliteral Eigenschaften / Methoden als übergeordnetes Element / Vorfahr hinzuzufügen.
Md. Zubaer Ahammed
@balajeerc 2. new Object (): In diesem Fall passiert fast dasselbe. Darüber hinaus ist es schlimmer, wenn Sie an das Gedächtnis denken. Anstatt die Eigenschaften und Methoden dem Prototyp zuzuweisen, kopiert es einfach alles aus dem übergebenen Objektliteral und fügt es in das zurückgegebene Objekt ein. Es ist nicht gut für das Gedächtnis. Andererseits habe ich mich auf die echte Vererbungskette mit einer Konstruktorfunktion konzentriert, mit der Sie Methoden und Eigenschaften im laufenden Betrieb bearbeiten können. Andere Objekte, die mit der Konstruktormethode erstellt wurden, sind ebenfalls betroffen, da sie nur auf diese Konstruktorfunktion verweisen (anstatt sie zu kopieren). .
Md. Zubaer Ahammed
@balajeerc Beispiel:function Person(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; } Person.prototype.fullname = function() { console.log(this.firstname + ' ' + this.lastname); } var zubaer = new Person('Zubaer', 'Ahammed'); var john = new Person('John', 'Doe'); zubaer.fullname(); // Zubaer Ahammed john.fullname(); // John Doe zubaer.constructor.prototype.fullname = function() { console.log( 'Hello ' + this.firstname); } zubaer.fullname(); // Hello Zubaer john.fullname(); // Hoello John
Md. Zubaer Ahammed
9

Auch nach einigen der O'Really-Javascript-Bücher .... (zitiert)

Ein weiterer Grund für die Verwendung von Literalen im Gegensatz zum Objektkonstruktor ist, dass es keine Bereichsauflösung gibt. Da Sie möglicherweise einen lokalen Konstruktor mit demselben Namen erstellt haben, muss der Interpreter die Bereichskette von der Stelle, an der Sie Object () aufrufen, bis zum Auffinden des globalen Objektkonstruktors nachschlagen.

adolfo_isassi
quelle
24
Warten Sie, war O'Really ein Tippfehler oder ein absichtliches Wortspiel? Sie sollten das für die Vermarktung ihrer Bücher verwenden!
Tim Ogilvy
3

Ich habe einen Unterschied für ES6 / ES2015 festgestellt. Sie können ein Objekt nicht mit der Kurzpfeil-Funktionssyntax zurückgeben, es sei denn, Sie umgeben das Objekt mit new Object().

> [1, 2, 3].map(v => {n: v});
[ undefined, undefined, undefined ]
> [1, 2, 3].map(v => new Object({n: v}));
[ { n: 1 }, { n: 2 }, { n: 3 } ]

Dies liegt daran, dass der Compiler durch die {}Klammern verwirrt ist und denkt, n: ies handele sich um ein Label: Anweisungskonstrukt ; Das Semikolon ist optional, damit es sich nicht darüber beschwert.

Wenn Sie dem Objekt eine weitere Eigenschaft hinzufügen, wird schließlich ein Fehler ausgegeben.

$ node -e "[1, 2, 3].map(v => {n: v, m: v+1});"
[1, 2, 3].map(v => {n: v, m: v+1});
                           ^

SyntaxError: Unexpected token :
Andrei Simionescu
quelle
4
Sie können immer noch eine Pfeilfunktion verwenden, Sie brauchen nur mehr Klammern und eine Rückkehr: [1, 2, 3].map(v => { return {n: v}; });Sie werden das gleiche Netz ...
Heretic Monkey
Natürlich können Sie reguläre Pfeilfunktionen verwenden. Ich habe über die Kurzversion gesprochen, dh über param => return_valueden Unterschied zwischen {}und new Object()in diesem Fall.
Andrei Simionescu
11
Sie können weiterhin die Kurzversion UND reguläre Pfeilfunktionen verwenden. Wickeln Sie einfach das {n: v} mit zwei Klammern ein:[1, 2, 3].map(v => ({n: v}));
Stephen C
1

Update 2019

Ich habe auf meinem OSX High Sierra 10.13.6-Knoten Version 10.13.0 denselben Code wie @rjloura ausgeführt, und dies sind die Ergebnisse

console.log('Testing Array:');
console.time('using[]');
for(var i=0; i<200000000; i++){var arr = []};
console.timeEnd('using[]');

console.time('using new');
for(var i=0; i<200000000; i++){var arr = new Array};
console.timeEnd('using new');

console.log('Testing Object:');

console.time('using{}');
for(var i=0; i<200000000; i++){var obj = {}};
console.timeEnd('using{}');

console.time('using new');
for(var i=0; i<200000000; i++){var obj = new Object};
console.timeEnd('using new');


Testing Array:
using[]: 117.613ms
using new: 117.168ms
Testing Object:
using{}: 117.205ms
using new: 118.644ms
PirateApp
quelle
-2

Die Speichernutzung ist unterschiedlich, wenn Sie 10.000 Instanzen erstellen. new Object()wird nur eine Kopie {}behalten, während zehntausend Kopien aufbewahrt werden.

Richard Miao US
quelle
7
newerstellt ein neues Objekt. Sie benötigen beide die gleiche Menge an Speicher.
Artyer