Quelle est la meilleure façon de créer un objet en JavaScript? «Var» est-il nécessaire avant une propriété d'objet?


177

Jusqu'à présent, j'ai vu trois façons de créer un objet en JavaScript. Quelle est la meilleure façon de créer un objet et pourquoi?

J'ai également vu que dans tous ces exemples, le mot var- clé n'est pas utilisé avant une propriété - pourquoi? N'est-il pas nécessaire de déclarer varavant le nom d'une propriété car il a mentionné que les propriétés sont des variables?

Dans la deuxième et la troisième manière, le nom de l'objet est en majuscules alors que dans la première manière le nom de l'objet est en minuscules. Quel cas devons-nous utiliser pour un nom d'objet?

Première manière:

function person(fname, lname, age, eyecolor){
  this.firstname = fname;
  this.lastname = lname;
  this.age = age;
  this.eyecolor = eyecolor;
}

myFather = new person("John", "Doe", 50, "blue");
document.write(myFather.firstname + " is " + myFather.age + " years old.");

Deuxième manière:

var Robot = {
  metal: "Titanium",
  killAllHumans: function(){
    alert("Exterminate!");
  }
};

Robot.killAllHumans();

Troisième manière - Objets JavaScript utilisant la syntaxe de tableau:

var NewObject = {};

NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }

2
le "var" est utilisé en fonction de la portée de la variable, il définit le global ou non, recherchez-le et vous verrez la différence.
jackJoe

80
si vous créez des robots homicides, utilisez toujours var, s'il vous plaît .. l'omettre les rend globaux
mykhal

9
"var est utilisé en fonction de la portée de la variable" - c'est une mauvaise pratique - il devrait être utilisé quelle que soit la portée dans laquelle vous vous
trouvez

1
Qu'en est-il de la méthode Object.create():?
Max

Ce serait bien si «comme il est mentionné que les propriétés sont des variables» était clarifié. Qu'est-ce"? Où cela est-il mentionné? Pouvez-vous citer un devis spécifique?
user4642212

Réponses:


181

Il n'y a pas meilleur moyen, cela dépend de votre cas d'utilisation.

  • Utilisez la méthode 1 si vous souhaitez créer plusieurs objets similaires. Dans votre exemple, Person(vous devriez commencer le nom par une majuscule) est appelée la fonction constructeur . Ceci est similaire aux classes dans d'autres langages OO.
  • Utilisez la méthode 2 si vous n'avez besoin que d' un seul objet d'un type (comme un singleton). Si vous voulez que cet objet hérite d'un autre, vous devez utiliser une fonction constructeur.
  • Utilisez la méthode 3 si vous souhaitez initialiser les propriétés de l'objet en fonction d'autres propriétés de celui-ci ou si vous avez des noms de propriétés dynamiques.

Mise à jour: comme demandé des exemples pour la troisième voie.

Propriétés dépendantes:

Ce qui suit ne fonctionne pas car thisne fait pas référence à book. Il n'existe aucun moyen d'initialiser une propriété avec des valeurs d'autres propriétés dans un littéral d'objet:

var book = {
    price: somePrice * discount,
    pages: 500,
    pricePerPage: this.price / this.pages
};

à la place, vous pouvez faire:

var book = {
    price: somePrice * discount,
    pages: 500
};
book.pricePerPage = book.price / book.pages;
// or book['pricePerPage'] = book.price / book.pages;

Noms de propriétés dynamiques:

Si le nom de la propriété est stocké dans une variable ou créé via une expression, vous devez utiliser la notation entre crochets:

var name = 'propertyName';

// the property will be `name`, not `propertyName`
var obj = {
    name: 42
}; 

// same here
obj.name = 42;

// this works, it will set `propertyName`
obj[name] = 42;

1
merci pour votre réponse ... maintenant j'ai compris votre premier point, nous pouvons utiliser way1 si nous voulons quelque chose comme ça myFather = new person ("John", "Doe", 50, "blue"); maMère = nouvelle personne ("gazy", "Doe", 45, "brown"); myBrother = nouvelle personne ("sondage", "Doe", 15, "blue");
Jamna

Je pense que vous voulez dire obj [nom] = 42. N'est-ce pas?
Keith Pinson

Je tiens à souligner que les options 2 et 3 sont pratiquement identiques, juste que vous attribuez des propriétés après avoir créé l'objet. C'est ce qu'on appelle la notation littérale , car vous utilisez un objet littéral pour créer votre objet. Sous le capot, cela appelle en fait "new Object ()". Vous pouvez en savoir plus ici: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
dudewad

Pour le second cas, serait-il logique d'utiliser l'opérateur de diffusion ...pour hériter d'un autre objet?
6pack kid

114

Il existe différentes manières de définir une fonction. Il est totalement basé sur vos besoins. Voici les quelques styles: -

  1. Constructeur d'objets
  2. Constructeur littéral
  3. Basé sur la fonction
  4. Basé sur Protoype
  5. Basé sur la fonction et le prototype
  6. Basé sur Singleton

Exemples:

  1. Constructeur d'objets
var person = new Object();

person.name = "Anand",
person.getName = function(){
  return this.name ; 
};
  1. Constructeur littéral
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 
  1. Constructeur de fonction
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
} 
  1. Prototype
function Person(){};

Person.prototype.name = "Anand";
  1. Combinaison fonction / prototype
function Person(name){
  this.name = name;
} 
Person.prototype.getName = function(){
  return this.name
} 
  1. Singleton
var person = new function(){
  this.name = "Anand"
} 

Vous pouvez l'essayer sur console, en cas de confusion.


HEy @Alex_Nabu - J'ai déjà partagé les exemples dans mon message. Si vous rencontrez toujours des difficultés, veuillez me mettre à jour, je vous aiderai.
Anand Deep Singh

1
ne serait-il pas plus judicieux de construire chaque exemple produisant exactement la même var personinstance à la fin? par exemple, dans le constructeur de fonction, vous pouvez simplement ajouter var person = new Person("Anand"). et qu'est-ce qui se passe avec l'utilisation apparemment aléatoire du point-virgule? : P
cregox

2
Cela ajouterait de la valeur en expliquant les avantages et les inconvénients de chaque manière.
RayLoveless

10

Il n'y a pas de «meilleure façon» de créer un objet. Chaque méthode présente des avantages en fonction de votre cas d'utilisation.

Le modèle de constructeur (une fonction associée au new opérateur pour l'invoquer) offre la possibilité d'utiliser l'héritage prototypique, contrairement aux autres méthodes. Donc, si vous voulez l'héritage prototypique, une fonction de constructeur est une bonne solution.

Cependant, si vous souhaitez l'héritage prototypique, vous pouvez également l'utiliser Object.create, ce qui rend l'héritage plus évident.

La création d'un objet littéral (ex:) var obj = {foo: "bar"};fonctionne très bien si vous avez toutes les propriétés que vous souhaitez définir au moment de la création.

Pour définir les propriétés ultérieurement, la NewObject.property1syntaxe est généralement préférable à NewObject['property1']si vous connaissez le nom de la propriété. Mais ce dernier est utile lorsque vous n'avez pas réellement le nom de la propriété à l'avance (ex:NewObject[someStringVar] .

J'espère que cela t'aides!


6

Je suppose que cela dépend de ce que vous voulez. Pour les objets simples, je suppose que vous pouvez utiliser les deuxièmes méthodes. Lorsque vos objets deviennent plus grands et que vous prévoyez d'utiliser des objets similaires, je suppose que la première méthode serait meilleure. De cette façon, vous pouvez également l'étendre à l'aide de prototypes.

Exemple:

function Circle(radius) {
    this.radius = radius;
}
Circle.prototype.getCircumference = function() {
    return Math.PI * 2 * this.radius;
};
Circle.prototype.getArea = function() {
    return Math.PI * this.radius * this.radius;
}

Je ne suis pas un grand fan de la troisième méthode, mais c'est vraiment utile pour éditer dynamiquement les propriétés, par exemple var foo='bar'; var bar = someObject[foo];.


3

Il existe de nombreuses façons de créer vos objets en JavaScript. Utiliser une fonction de constructeur pour créer un objet ou une notation littérale d'objet utilise beaucoup en JavaScript. En créant également une instance d'Object, puis en y ajoutant des propriétés et des méthodes, il existe trois façons courantes de créer des objets en JavaScript.

Fonctions du constructeur

Il existe des fonctions de constructeur intégrées que nous pouvons tous utiliser de temps en temps, comme Date (), Number (), Boolean (), etc., toutes les fonctions de constructeur commencent par une majuscule, en attendant, nous pouvons créer une fonction de constructeur personnalisée en JavaScript comme ça:

function Box (Width, Height, fill) {  
  this.width = Width;  // The width of the box 
  this.height = Height;  // The height of the box 
  this.fill = true;  // Is it filled or not?
}  

et vous pouvez l'invoquer, simplement en utilisant new (), pour créer une nouvelle instance du constructeur, créer quelque chose comme ci-dessous et appeler la fonction constructeur avec des paramètres remplis:

var newBox = new Box(8, 12, true);  

Objets littéraux

L'utilisation de littéraux d'objet est très utilisée dans le cas de la création d'objet en JavaScript, c'est un exemple de création d'un objet simple, vous pouvez attribuer n'importe quoi à vos propriétés d'objet tant qu'elles sont définies:

var person = { 
    name: "Alireza",
    surname: "Dezfoolian"
    nose: 1,  
    feet: 2,  
    hands: 2,
    cash: null
};  

Prototypage

Après avoir créé un objet, vous pouvez créer un prototype de plus de membres, par exemple en ajoutant de la couleur à notre boîte, nous pouvons le faire:

Box.prototype.colour = 'red';

2

Alors que beaucoup de gens ici disent qu'il n'y a pas de meilleur moyen de créer des objets, il y a une raison pour laquelle il y a tant de façons de créer des objets en JavaScript, à partir de 2019, et cela a à voir avec la progression de JavaScript au cours des différentes itérations. des versions d'EcmaScript datant de 1997.

Avant ECMAScript 5, il n'y avait que deux façons de créer des objets: la fonction constructeur ou la notation littérale (une meilleure alternative à new Object ()). Avec la notation de fonction constructeur, vous créez un objet qui peut être instancié dans plusieurs instances (avec le nouveau mot-clé), tandis que la notation littérale délivre un seul objet, comme un singleton.

// constructor function
function Person() {};

// literal notation
var Person = {};

Quelle que soit la méthode que vous utilisez, les objets JavaScript sont simplement des propriétés de paires valeur / clé:

// Method 1: dot notation
obj.firstName = 'Bob';

// Method 2: bracket notation. With bracket notation, you can use invalid characters for a javascript identifier.
obj['lastName'] = 'Smith';

// Method 3: Object.defineProperty
Object.defineProperty(obj, 'firstName', {
    value: 'Bob',
    writable: true,
    configurable: true,
    enumerable: false
})

// Method 4: Object.defineProperties
Object.defineProperties(obj, {
  firstName: {
    value: 'Bob',
    writable: true
  },
  lastName: {
    value: 'Smith',
    writable: false
  }
});

Dans les premières versions de JavaScript, le seul véritable moyen d'imiter l'héritage basé sur les classes était d'utiliser des fonctions de constructeur. la fonction constructeur est une fonction spéciale qui est appelée avec le mot-clé 'new'. Par convention, l'identifiant de la fonction est en majuscule, albiet il n'est pas obligatoire. À l'intérieur du constructeur, nous nous référons au mot-clé «this» pour ajouter des propriétés à l'objet que la fonction constructeur crée implicitement. La fonction constructeur renvoie implicitement le nouvel objet avec les propriétés remplies à la fonction appelante implicitement, sauf si vous utilisez explicitement le mot-clé return et retournez autre chose.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    this.sayName = function(){
        return "My name is " + this.firstName + " " + this.lastName;
    }
} 

var bob = new Person("Bob", "Smith");
bob instanceOf Person // true

Il y a un problème avec la méthode sayName. En règle générale, dans les langages de programmation basés sur des classes orientées objet, vous utilisez des classes comme usines pour créer des objets. Chaque objet aura ses propres variables d'instance, mais il aura un pointeur vers les méthodes définies dans le plan de classe. Malheureusement, lors de l'utilisation de la fonction constructeur de JavaScript, chaque fois qu'elle est appelée, elle définira une nouvelle propriété sayName sur l'objet nouvellement créé. Ainsi, chaque objet aura sa propre propriété sayName unique. Cela consommera plus de ressources mémoire.

Outre l'augmentation des ressources de mémoire, la définition de méthodes à l'intérieur de la fonction constructeur élimine la possibilité d'héritage. Encore une fois, la méthode sera définie comme une propriété sur l'objet nouvellement créé et aucun autre objet, donc l'héritage ne peut pas fonctionner comme. Par conséquent, JavaScript fournit la chaîne de prototypes comme une forme d'héritage, faisant de JavaScript un langage prototypique.

Si vous avez un parent et qu'un parent partage de nombreuses propriétés d'un enfant, l'enfant doit hériter de ces propriétés. Avant ES5, il était accompli comme suit:

function Parent(eyeColor, hairColor) {
    this.eyeColor = eyeColor;
    this.hairColor = hairColor;
}

Parent.prototype.getEyeColor = function() {
  console.log('has ' + this.eyeColor);
}

Parent.prototype.getHairColor = function() {
  console.log('has ' + this.hairColor);
}

function Child(firstName, lastName) {
  Parent.call(this, arguments[2], arguments[3]);
  this.firstName = firstName;
  this.lastName = lastName;
}

Child.prototype = Parent.prototype;

var child = new Child('Bob', 'Smith', 'blue', 'blonde');
child.getEyeColor(); // has blue eyes
child.getHairColor(); // has blonde hair

La façon dont nous avons utilisé la chaîne de prototypes ci-dessus a une bizarrerie. Étant donné que le prototype est un lien actif, en modifiant la propriété d'un objet dans la chaîne de prototypes, vous changeriez également la même propriété d'un autre objet. Évidemment, changer la méthode héritée d'un enfant ne devrait pas changer la méthode du parent. Object.create a résolu ce problème en utilisant un polyfill. Ainsi, avec Object.create, vous pouvez modifier en toute sécurité la propriété d'un enfant dans la chaîne de prototypes sans affecter la même propriété du parent dans la chaîne de prototypes.

ECMAScript 5 a introduit Object.create pour résoudre le bogue susmentionné dans la fonction constructeur pour la création d'objets. La méthode Object.create () CRÉE un nouvel objet, en utilisant un objet existant comme prototype de l'objet nouvellement créé. Puisqu'un nouvel objet est créé, vous n'avez plus le problème où la modification de la propriété enfant dans la chaîne prototype modifiera la référence du parent à cette propriété dans la chaîne.

var bobSmith = {
    firstName: "Bob",
    lastName: "Smith",
    sayName: function(){
      return "My name is " + this.firstName + " " + this.lastName;
    }
}

var janeSmith = Object.create(bobSmith, {
    firstName : {  value: "Jane" }
})

console.log(bobSmith.sayName()); // My name is Bob Smith
console.log(janeSmith.sayName()); // My name is Jane Smith
janeSmith.__proto__ == bobSmith; // true
janeSmith instanceof bobSmith; // Uncaught TypeError: Right-hand side of 'instanceof' is not callable. Error occurs because bobSmith is not a constructor function.

Avant ES6, voici un modèle de création commun pour utiliser les constructeurs de fonctions et Object.create:

const View = function(element){
  this.element = element;
}

View.prototype = {
  getElement: function(){
    this.element
  }
}

const SubView = function(element){
  View.call(this, element);
}

SubView.prototype = Object.create(View.prototype);

Désormais, Object.create, associé à des fonctions de constructeur, a été largement utilisé pour la création et l'héritage d'objets en JavaScript. Cependant, ES6 a introduit le concept de classes, qui sont principalement du sucre syntaxique par rapport à l'héritage basé sur prototype existant de JavaScript. La syntaxe de classe n'introduit pas de nouveau modèle d'héritage orienté objet dans JavaScript. Ainsi, JavaScript reste un langage prototypique.

Les classes ES6 rendent l'héritage beaucoup plus facile. Nous n'avons plus besoin de copier manuellement les fonctions prototypes de la classe parent et de réinitialiser le constructeur de la classe enfant.

// create parent class
class Person {
  constructor (name) {
    this.name = name;
  }
}

// create child class and extend our parent class
class Boy extends Person {
  constructor (name, color) {
    // invoke our parent constructor function passing in any required parameters
    super(name);

    this.favoriteColor = color;
  }
}

const boy = new Boy('bob', 'blue')
boy.favoriteColor; // blue

Au total, ces 5 stratégies différentes de création d'objets en JavaScript ont coïncidé avec l'évolution du standard EcmaScript.


0

Bien sûr, il existe un meilleur moyen: les objets en javascript ont des propriétés énumérables et non énumérables.

var empty = {};
console.log(empty.toString);
// . function toString(){...}
console.log(empty.toString());
// . [object Object]

Dans l'exemple ci-dessus, vous pouvez voir qu'un objet vide a en fait des propriétés.

Ok d'abord voyons quel est le meilleur moyen:

var new_object = Object.create(null)

new_object.name = 'Roland'
new_object.last_name = 'Doda'
//etc

console.log("toString" in new_object) //=> false

Dans l'exemple ci-dessus, le journal affichera false.

Voyons maintenant pourquoi les autres méthodes de création d'objets sont incorrectes.

//Object constructor
var object = new Object();

console.log("toString" in object); //=> true

//Literal constructor
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 

console.log("toString" in person); //=> true

//function Constructor
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
}

var person = new Person ('landi')

console.log("toString" in person); //=> true

//Prototype
function Person(){};

Person.prototype.name = "Anand";

console.log("toString" in person); //=> true

//Function/Prototype combination
function Person2(name){
  this.name = name;
} 

Person2.prototype.getName = function(){
  return this.name
}

var person2 = new Person2('Roland')

console.log("toString" in person2) //=> true

Comme vous pouvez le voir ci-dessus, tous les exemples consignent true, ce qui signifie que si vous avez un cas où vous avez une for inboucle pour voir si l'objet a une propriété, vous obtiendrez probablement des résultats erronés.

Notez que la meilleure façon ce n'est pas facile. Vous devez définir toutes les propriétés de l'objet ligne par ligne. Les autres méthodes sont plus faciles et auront moins de code pour créer un objet mais vous devez être conscient dans certains cas. J'utilise toujours les "autres moyens" au fait et une solution à l'avertissement ci-dessus si vous n'utilisez pas la meilleure méthode est:

 for (var property in new_object) {
  if (new_object.hasOwnProperty(property)) {
    // ... this is an own property
  }
 }

0

Il existe principalement 3 façons de créer des objets -

Le plus simple consiste à utiliser des littéraux d'objet .

const myObject = {}

Bien que cette méthode soit la plus simple mais présente un inconvénient, c'est-à-dire que si votre objet a un comportement (des fonctions en lui), à l'avenir, si vous voulez y apporter des modifications, vous devrez le changer dans tous les objets .

Donc, dans ce cas, il est préférable d'utiliser les fonctions Factory ou Constructor. (N'importe qui que vous aimez)

Les fonctions d'usine sont les fonctions qui renvoient un objet.

function factoryFunc(exampleValue){
   return{
      exampleProperty: exampleValue 
   }
}

Les fonctions de constructeur sont ces fonctions qui attribuent des propriétés aux objets en utilisant le mot-clé "this" .eg-

function constructorFunc(exampleValue){
   this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.