Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

JavaScript: objet, la pratique

Poster un commentaire

Nous venons de voir en détails les différentes façons de créer un objet.

Maintenant vous êtes devant votre code et ça devient sérieux. La théorie c’est bien, mais en pratiques je dois faire quoi? Quels sont les pièges et les anti patterns?

On va voir comment on utilise nos nouvelles connaissances dans quelques situations pratiques.

Membres privés et membres statiques

Dans l’article précédent on a présenté le code suivant:

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

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

Regardez le petit changement suivant d’apparence anodine:

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

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

var fact = new Facture(456, « Amethyste »);

alert(fact.id); // undefined

fact.toString(); // 456:Amethyste

Le paramètre id n’est plus déclaré avec this, mais var. Et le comportement de l’objet change.

On constate que le paramètre id n’est plus accessible depuis l’extérieur, mais reste visible de l’intérieur de l’objet grâce à la closure. En somme, JavaScript dispose de la notion de membres privés.

On peut même développer une notion de membre statique:

function Facture() {};

facture.Constante = ‘123456’;

var fact = new Facture();

alert(facture.Constante); // 123456

alert(fact.Constante); // undefined

Comme en C# c’est l’objet que l’on doit considérer, pas l’instance.

Que se passerait t’il si on ne mettait ni var, ni this?

function Facture(id) {
id=id;
    this.toString = function () { alert(this.id);};
}

var fact= new Facture(5);
fact.toString(); // undefined

Eh oui id est undefined.

Mais ceci marche:

function Facture(id) {
id=id;
    this.toString = function () { alert(id);};
}

En l’absence de var et this, la propriété est en effet rattachée au scope global. Choix bizarre de JavaScript.

C’est très général, déclarer une propriété ou une variable sans var, l’attache toujours au scope global.

Retour sur le pattern constructeur

Le pattern constructeur utilise une fonction pour créer un objet, par exemple:

function Facture(id)
{
       this.id=id;
       this.display = function () {alert(this.id) }
}

La création de l’objet se fait avec le mot clef new:

var fact = new Facture(123);
fact.display(); // 123

La fonction est une fonction comme les autres et on pourrait être tenté de se passer du mot clef new. Essayons:

var fact = Facture(123);
fact.display();

Un message d’erreur apparait. Et c’est normal si vous avez bien suivit l’article sur this car dans ce cas this représente le scope global qui ne contient évidemment pas display().

Le mot clef new indique donc à l’interpréteur JavaScript d’associer l’instance de l’objet à this. C’est justement pour rappeler cette nécessité, c’est à dire que Facture n’est pas tout à fait une fonction, que la méthode est mise en majuscule.

C’est une construction évidemment très fragile que beaucoup de développeurs découragent. Oui, mais pour quelle alternative?

On a déjà vu une possibilité avec Object.create(). Il existe un pattern beaucoup plus répandu appelé pattern factory.

Une factory est simplement une fonction normale qui retourne une instance d’objet. Par exemple:

function createCar() {
         return {marque: ‘Clio’};
}

Un autre exemple serait:

function factureFactory() {
var fact = new function Animal() {};
    fact.total = function() { alert(345);}

     return fact
}

var fact = factureFactory();
fact.total(); // 345

Le principe est toujours le même. On instancie pas directement l’objet, on sous-traite le travail à une fonction intermédiaire appelée factory. Son rôle est d’encapsuler toute la logique de création de l’objet, en particulier le new, et de retourner l’objet ainsi créé.

Contrairement au constructeur le nom de la factory n’est pas en majuscule car il s’agit d’une fonction ordinaire. Cela pourrait même perturber des analyseurs de code comme JsLint.

Un des intérêts de la factory est de fournir un moyen simple d’encapsuler des logiques de création un peu complexe (ajout de propriétés, de fonctions, initialisation…) sans avoir à la recopier partout où on a besoin d’une instance de l’objet.
Un cas particulier est la prise en charge du polymorphisme en JavaScript.

Il y a encore pas mal de chose à dire sur l’instanciation des objets en JavaScript. Ce n’est pas un langage bien conçu de ce point de vue et cette opération est complexe et sujette à pas mal de bugs.

Diverses choses

  • L’opérateur || permet de définir une valeur par défaut pour le cas où l’on appelle un membre non définit:

var adresse = facture.AdresseClient || ‘Par la bas’;

  •  En JavaScrit un objet est toujours passé par référence.

 

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