Quelle est la différence entre cette syntaxe basée sur le constructeur pour créer un objet:
person = new Object()
... et cette syntaxe littérale:
person = {
property1 : "Hello"
};
Il semble que les deux fassent la même chose, bien que JSLint préfère que vous utilisiez la notation littérale d'objet.
Lequel est le meilleur et pourquoi?
Ils font tous les deux la même chose (sauf si quelqu'un a fait quelque chose d'inhabituel), sauf que votre deuxième crée un objet et lui ajoute une propriété. Mais la notation littérale prend moins de place dans le code source. C'est clairement reconnaissable quant à ce qui se passe, donc en utilisant new Object()
, vous en saisissez simplement plus et (en théorie, si ce n'est optimisé par le moteur JavaScript), vous appelez une fonction inutile.
Celles-ci
person = new Object() /*You should put a semicolon here too.
It's not required, but it is good practice.*/
-or-
person = {
property1 : "Hello"
};
techniquement, ne faites pas la même chose. Le premier crée simplement un objet. Le second en crée un et attribue une propriété. Pour que le premier soit identique, vous avez besoin d’une deuxième étape pour créer et attribuer la propriété.
Le "quelque chose d'inhabituel" que quelqu'un pourrait faire serait de masquer ou d'assigner à la valeur par défaut Object
global:
// Don't do this
Object = 23;
Dans ce cas très inhabituel, new Object
échouera mais {}
fonctionnera.
En pratique, il n'y a jamais de raison d'utiliser new Object
plutôt que {}
(à moins que vous n'ayez fait cette chose très inhabituelle).
Il n'y a pas de différence pour un objet simple sans méthodes, comme dans votre exemple. Cependant, il y a une grande différence lorsque vous commencez à ajouter des méthodes à votre objet.
Manière littérale:
function Obj( prop ) {
return {
p : prop,
sayHello : function(){ alert(this.p); },
};
}
Manière prototype:
function Obj( prop ) {
this.p = prop;
}
Obj.prototype.sayHello = function(){alert(this.p);};
Les deux méthodes permettent de créer des instances de Obj
comme ceci:
var foo = new Obj( "hello" );
Cependant, avec la méthode littérale, vous emportez une copie de la méthode sayHello
dans chaque instance de vos objets. Considérant que, avec la méthode prototype, la méthode est définie dans le prototype d'objet et partagée entre toutes les instances d'objet. Si vous avez beaucoup d'objets ou beaucoup de méthodes, la manière littérale peut vous conduire à beaucoup de perte de mémoire.
En JavaScript, nous pouvons déclarer un nouvel objet vide de deux manières:
var obj1 = new Object();
var obj2 = {};
Je n'ai rien trouvé qui donne à penser qu'il existe une différence significative entre ces deux personnes en ce qui concerne leur fonctionnement en coulisse (corrigez-moi si je me trompe - j'aimerais bien le savoir). Cependant, la seconde méthode (utilisant la notation littérale d'objet) offre quelques avantages.
Considérons un nouvel objet contenant les membres Name et TelNo. En utilisant la nouvelle convention Object (), nous pouvons le créer comme ceci:
var obj1 = new Object();
obj1.Name = "A Person";
obj1.TelNo = "12345";
La fonctionnalité Expando Properties de JavaScript nous permet de créer de nouveaux membres de cette manière à la volée et nous réalisons ce que nous avions l'intention de faire. Cependant, cette manière n’est pas très structurée ou encapsulée. Et si nous voulions spécifier les membres lors de la création, sans avoir à compter sur les propriétés expando et les attributions post-création?
C’est là que la notation littérale d’objet peut aider:
var obj1 = {Name:"A Person",TelNo="12345"};
Ici, nous avons obtenu le même effet avec une ligne de code et beaucoup moins de caractères.
Une discussion plus approfondie des méthodes de construction d'objet ci-dessus est disponible à l'adresse suivante: JavaScript et programmation orientée objet (OOP).
Et enfin, qu'en est-il de l'idiot qui a écrasé Object? Pensiez-vous que ce n’était pas possible? Eh bien, ce JSFiddle prouve le contraire. L'utilisation de la notation littérale d'objet nous empêche de tomber sous le charme de cette bouffonnerie.
(De http://www.jameswiseman.com/blog/2011/01/19/jslint-messages-use-the-object-literal-notation/ )
Sur ma machine utilisant Node.js, j’ai exécuté:
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');
Notez que ceci est une extension de ce qui se trouve ici: Pourquoi arr = [] est-il plus rapide que arr = new Array?
ma sortie était la suivante:
Testing Array:
using[]: 1091ms
using new: 2286ms
Testing Object:
using{}: 870ms
using new: 5637ms
si clairement {} et [] sont plus rapides que l’utilisation de new pour la création d’objets/de tableaux vides.
Tout le monde ici parle des similitudes des deux. Je vais souligner les différences.
Utiliser new Object()
vous permet de transmettre un autre objet. Le résultat évident est que l'objet nouvellement créé sera défini sur la même référence. Voici un exemple de code:
var obj1 = new Object();
obj1.a = 1;
var obj2 = new Object(obj1);
obj2.a // 1
L'utilisation n'est pas limitée aux objets comme dans les objets OOP. D'autres types pourraient également lui être transmis. La fonction définira le type en conséquence. Par exemple, si nous lui passons l'entier 1, un objet de type numéro sera créé pour nous.
var obj = new Object(1);
typeof obj // "number"
L'objet créé à l'aide de la méthode ci-dessus (new Object(1)
) serait converti en type d'objet si une propriété lui était ajoutée.
var obj = new Object(1);
typeof obj // "number"
obj.a = 2;
typeof obj // "object"
Si l'objet est une copie d'une classe d'objet enfant, nous pourrions ajouter la propriété sans conversion de type.
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
En fait, il existe plusieurs façons de créer des objets en JavaScript. Lorsque vous souhaitez simplement créer un objet, la création d'objets "basés sur le constructeur" à l'aide de l'opérateur "new" ne présente aucun avantage. C'est comme créer un objet en utilisant la syntaxe "object literal". Mais les objets "basés sur le constructeur" créés avec l'opérateur "nouvea" ont une utilisation incroyable lorsque vous songez à "héritage prototype". Vous ne pouvez pas gérer la chaîne d'héritage avec des objets créés avec une syntaxe littérale. Mais vous pouvez créer un fonction constructeur, attacher des propriétés et des méthodes à son prototype. Ensuite, si vous affectez cette fonction constructeur à n’importe quelle variable à l’aide de l’opérateur "new", elle renverra un objet qui aura accès à toutes les méthodes et propriétés attachées au prototype de cette fonction constructeur.
Voici un exemple de création d'un objet à l'aide de la fonction constructeur (voir l'explication du code en bas):
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();
Maintenant, vous pouvez créer autant d'objets que vous le souhaitez en instanciant la fonction de construction de Personne. Tous hériteront de fullname ().
Remarque: le mot clé "this" fait référence à un objet vide dans une fonction constructeur et chaque fois que vous créez un nouvel objet à partir de Person à l'aide de l'opérateur "new", cet objet renvoie automatiquement un objet. contenant toutes les propriétés et méthodes attachées avec le mot clé "this". Et ces objets hériteront à coup sûr des méthodes et propriétés attachées à la fonction prototype de la fonction constructeur Person (qui constitue l’avantage principal de cette approche).
En passant, si vous voulez obtenir les mêmes fonctionnalités avec la syntaxe "littéral d'objet", vous devez créer un nom complet () avec tous les objets, comme ci-dessous:
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();
Enfin, si vous demandez maintenant pourquoi devrais-je utiliser l'approche fonction constructeur au lieu de l'approche littéral d'objet:
*** L'héritage prototypique permet une chaîne simple d'héritage qui peut être extrêmement utile et puissant.
*** Il économise de la mémoire en héritant des méthodes et propriétés communes définies dans le prototype de fonctions de constructeur. Sinon, vous devrez les copier encore et encore dans tous les objets.
J'espère que cela a du sens.
En outre, selon certains livres O'Really en javascript .... (cité)
Une autre raison d'utiliser des littéraux par opposition au constructeur Object est qu'il n'y a pas de résolution de portée. Comme il est possible que vous ayez créé un constructeur local portant le même nom, l’interprète doit rechercher la chaîne de portées à partir de l’emplacement où vous appelez Object () jusqu’à ce qu’il trouve le constructeur global Object.
J'ai trouvé une différence, pour ES6/ES2015. Vous ne pouvez pas renvoyer d'objet à l'aide de la syntaxe de fonction de flèche abrégée, sauf si vous entourez l'objet avec 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 } ]
Ceci est dû au fait que le compilateur est confus par les crochets {}
et pense que n: i
est un label: statement construct; le point-virgule est facultatif, donc il ne s'en plaint pas.
Si vous ajoutez une autre propriété à l'objet, une erreur sera finalement générée.
$ 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 :
Mise à jour 2019
J'ai exécuté le même code que @rjloura sur mon noeud OSX High Sierra 10.13.6 version 10.13.0 et voici les résultats
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