Dans l'article du pattern décoration, nous avons vu comment une fonction peut augmenter (décorer) un objet existant.
Reprenons cet exemple :
A noter l'erreur de code loc = pos car la fonction carlike.
La fonction carlike décore l'objet obj qui lui est passé en paramètre.
Nous allons renommer et modifier la fonction pour qu'elle génère les objets.
Le paramètre obj est remplacé par une déclaration de variable locale var obj = {...}.
A l'inverse de la fonction de décoration qui modifie un objet existant, la fonction Car crée ici l'objet obj et le retournera.
Notez la convention d'écriture de cette fonction : Le nom commence par une Majuscule.
Nous venons de définir ce que l'on appelle un constructeur. L'appel de cette fonction, une instanciation, retourne un objet de type Car. L'objet aCar est une instance. Les objets générés possèdent une propriété pos et une fonction move.
Nous avons déjà vu dans l'article pattern décoration que chaque objet possède sa propre fonction move. En sortant la fonction du constructeur, chaque objet va pointer sur la fonction move ce qui évite la duplication coûteuse en mémoire.
En sortant la fonction move du constructeur, nous n'avons pas conservé la closure et nous remplaçons obj par this. This sera l'objet placé à gauche de l'appel de la fonction. lorsque nous écrirons bcar.move() this sera lié à bcar.
Amélirations
Nous devons améliorer notre écriture, en effet, considérons que nous avons une vingtaine de fonctions identiques à move à écrire, ces fonctions apparaîtrons à deux endroits.
Nous regroupons les fonctions dans un objet methods. L'ajout d'une nouvelle fonction en ligne 12 ne modifie en rien (ligne 4) le constructeur Car.
Mais, en lisant le code, nous remarquons que l'objet methods n'est en rien lié à Car. Ainsi, pour améliorer la lisibilité, nous ajoutons methods comme propriété de la fonction Car. Ce qui évite en plus la création d'une variable globale methods.
Rappel : une fonction est un objet, un objet peut avoir des propriétés et méthodes. Il en est de même pour les fonction ! Une différence est que les fonctions peuvent être appelées.
Dans cette article, nous avons vue comment une fonction peut être considérée comme une classe. Dans d'autres articles, nous introduirons des amélioration de performance avec la chaîne de prototype : un des fondement de JS.
Annexe :
Pour la fonction extend(obj1,obj2), on pourra trouver des exemples de code sur le web.
Dans la bibliothèque jquery
L'idée générale est recopier chaque propriété de l'objet2 dans l'objet1.
var __slice = [].slice;
function extend () {
var consumer = arguments[0],
providers = __slice.call(arguments, 1),
key,
i,
provider;
for (i = 0; i < providers.length; ++i) {
provider = providers[i];
for (key in provider) { // pour toutes les methodes et propriétés
if (provider.hasOwnProperty(key)) { //oublions la chaîne de prototype
consumer[key] = provider[key]; // création d'une prop key et recopie
};
};
};
return consumer;
};
extend(sam, person);
sam.rename