Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

JavaScript: diverses façon de créer un objet

Poster un commentaire

JavaScript, sans être strictement parlant un langage objet, apporte un support dans ce domaine.

Ceci dit c’est assez dépaysant lorsque l’on vient de C#. Pas de notions de classe, mais une syntaxe qui hésite entre plusieurs voies contradictoires et quelques pièges.

La maîtrise des objets demandera un certain chalenge. Peut être qu’un jour les outils de développement JavaScript auront la précision de ceux d’autres langages, mais en attendant faisons le point à l’ancienne sur les choses à connaître!

Je ne prétends nullement faire le document définitif sur la question, j’essaye juste de définir ce qui est le minimum à connaitre sur la question.

Avant de lire cet article, rafraîchissez vos connaissances sur les espaces de noms et this.
This est la principale source de problème avec les objets.

  • Les littéraux d’objet
  • Construction avec new
  • Les prototypes
  • La méthode Object.create()

Les littéraux d’objet

Les littéraux d’objets, sont un moyen de déclarer un objet directement avec une expression dans le style Json:

Par exemple:

var facture = {
client: « Amethyste »,
identifiant: 50489,
details: [
{ article: « sapin de Noel »,   categorie: « Déco »,         « prix euro »: 23.4     }
, { article: « Saumon »,    categorie: « Bouffe »,         « prix euro »: 27.5     }
, { article: « Champagne »,   categorie: « Bouffe »,         « prix euro »: 80     }
]
};

alert(facture.client); // Amethyste
alert(facture.details.length); // 3

var detail = facture.details[0];
alert(detail[« prix euro »]); // 23.4

Important: ne pas mettre de tabulations, juste des espaces.

  • La syntaxe comprend une accolade ouvrante et se termine par une accolade fermante.
  • Pas de guillemets.
  • Des doubles points (:) sépare identifiant et expression
  • des virgules séparent les membres

Mais attention, ce n’est pas exactement du Json. Une syntaxe Json ressemblerait à ceci et est tout à fait acceptable pour créer un objet:

var facture =  {
    « client »: « Amethyste »,
    « identifiant »: 50489,
    « details »: [
        {
            « article »: « sapin de Noel »,
            « categorie »: « Déco »,
            « prix euro »: 23.4
        },
        {
            « article »: « Saumon »,
            « categorie »: « Bouffe »,
            « prix euro »: 27.5
        },
        {
            « article »: « Champagne »,
            « categorie »: « Bouffe »,
            « prix euro »: 80
        }
    ]
};

Notez la propriété « prix euro » qui a un espace dans son nom et la façon dont on y accède par la suite. On a donc deux syntaxe pour accéder à une propriété.
En JavaScript un objet est un conteneur avec entre autre un dictionnaire de propriété/valeur.

On peut également ajouter des fonctions comme pour tout objet:

facture.total = function () {
var montant = 0;


for (var i=0;i< this.details.length;i++) {
montant = montant + this.details[i][« prix euro »];
}
return montant;
};

alert(facture.total()); // 130.9

Notez le rôle que joue this dans cette déclaration. Le mot clef this a été étudié en détails dans cet article et vous devez donc savoir que sans lui le code ne marcherai pas et un message indiquant que détails est undefined s’afficherai.

On peut initialiser un objet vide:

var facture = {};

Puis le compléter à la volée:

facture.client = « Amethyste »;

Cette déclaration est parfaitement équivalente à:

var facture = new Object();

Le pattern constructeur

L’exemple juste au dessus laisse entrevoir une autre possibilité peut être plus naturelle pour un développeur C#: le constructeur.

Un constructeur est une fonction destinée à être utilisée avec le préfixe new. Par convention on les écrit en PascalCase.

On déclare une fonction:

function Facture(id,client) {
this.id=id;
this.client=client;

this.toString = function () { alert(id + « : » + client);};
}

Celle-ci nous sert de constructeur pour créer une instance d’objet.

var fact = new Facture(456, « Amethyste »); // création de l’instance d’objet

alert(fact.id); // 456
fact.toString(); // 456:Amethyste

Dans cette syntaxe this représente l’instance de l’objet en cours et non pas le propriétaire de la fonction. Nous reviendrons sur ce point dans un autre article.

Le pattern prototypes

Les prototypes et l’héritage par prototype sont ce qui différencient profondément JavaScript des autres langages objet. JavaScript ne connaît pas l’héritage par classe, il ne propose que l’héritage par prototype qui permet par exemple d’hériter directement d’une instance d’objet!

Chaque objet JavaScript se voit attribuer un second objet qui lui est associé. Ce second objet est le prototype. Le premier objet hérite des propriétés du prototype.

Il faut retenir ceci:

  • Les objets créés avec la notation littérale ont le même prototype: Object.prototype.
  • Les objets créés avec new suivit d’un constructeur prennent la valeur du prototype du constructeur.
  • prototype est un objet comme un autre, on peut lui ajouter des propriétés
  • Toutes les instances d’un type partagent les membres du prototype

Mais à quel prototype est associé Object.prototype? C’est l’exception, à aucun.

Nous allons pour la suite considérer cet objet:

function Personne(nom, prenom) {
     this.nom=nom;
     this.prenom =prenom;
}

Premier essai:

Personne.display = function(msg) {alert(msg + ‘: ‘ + this.nom)};
Personne.display(Salut); // salut: undefined

var untel=new Personne(‘Amethyste’,’Super’);
untel.display(‘Hello’); // display undefined

La première popup affiche ‘Salut: ‘undefined.
Cela montre juste un comportement que nous avons déjà vu avec les membres statique.
Plus intéressant est le deuxième appel à display. En fait un message d’erreur nous informe que display est undefined.

Donc si display est dans le scope de Personne, il ne l’est pas dans celui de untel. On vérifie donc qu’un membre attaché à l’objet, n’est pas hérité.

On peux modifier les choses ainsi:

Personne.prototype.display = function(msg) {alert(msg + ‘: ‘ + this.nom)};

var untel=new Personne(‘Amethyste’,’Super’);
untel.display(‘Hello’); // hello: Amethyste

Cette fois l’affichage est l’affichage prévu. De plus on constate que Customer.display ne marche pas.

On a donc bien vérifié la propriété fondamentale de prototype: un membre attaché à prototype sera hérité par les descendants.

Les membres de prototype peuvent t’ils se voir? Oui bien sûr:

function Personne() {

}

Personne.prototype.pseudo=’Amethyste’;
Personne.prototype.display = function() {alert(this.pseudo)};

 var untel=new Personne();
untel.display(); //  Amethyste

Par contre une propriété privée (déclarée avec var) n’est pas accessible.

La méthode Object.create()

Regardons ce code:

function Personne(nom) {
this.nom=nom;
}

Personne.prototype = {
quiEstLa : function() {alert(this.nom);}
}

var personne = Object.create(Personne.prototype);
personne.nom=’Amethyste’;

personne.quiEstLa(); // Amethyste

Aucune difficultés, la méthode fait ce qu’elle annonce: créer un objet.

Bien sûr ce qui peut paraître étrange est la façon de passer les paramètres de l’objet alors que l’on dispose d’un constructeur qui fait le boulot. On dispose d’une autre syntaxe plus cohérente:

function Personne(nom) {
this.nom=nom;
}

Personne.prototype = {
quiEstLa : function() {alert(this.nom);}
}

var personne = Object.create(Personne.prototype, {
          nom: {value: « Amethyste », writable:true, configurable:true} // descripteur de la propriété nom
                                    } );

Mais plus complète. Dans cette syntaxe il est possible d’attribuer un descripteur à chaque propriété ce que l’on ne pouvait pas faire avec les syntaxes précédentes.

Cette syntaxe est relativement récente, vérifiez bien sa compatibilité avec les navigateurs.

personne.quiEstLa(); // Amethyste

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s