Mal aimé, le JavaScript est un langage objet (Programmation orientée objet ou POO (un objet en programmation c’est la représentation « d’un concept, d’une idée » avec ses méthodes et ses propriétés). En fait le JavaScript ne possède que des objets. Outre les valeurs « null » et « undefined », tout en JavaScript agit comme un objet. Même si certains trouvent sa lecture quelque peu chaotique, le bénéfice est une flexibilité sans pareil!
L’exemple suivant parle de lui même, où une valeur booléenne « false » peut se convertir en chaine de caractère et retourner 'false'. Même chose avec la liste de nombres entiers 1,2 et 3...
Chaque objet JavaScript a un prototype et le prototype est aussi un objet.
« Tous les objets JavaScript héritent de leurs propriétés et méthodes de leur prototype : Object.prototype »
<script> console.log(false.toString()); // 'false' console.log([1, 2, 3].toString()); // '1,2,3' </script>
Même s’il s’apparente beaucoup au C++ ou au Java (basés sur des classes), le JavaScript est un langage orientés objet basé sur des prototypes.
<script> function oPersonne(){} oPersonne.nom = 'Luc Tremblay'; console.log(oPersonne.nom); // Luc Tremblay </script>
Comparaison d’un prototype JavaScript avec une classe Java
// JavaScript function Employe () { this.nom = ''; this.prenom = ''; } // Java public class Employe { public String nom; public String prenom; public Employe () { this.nom = ''; this.prenom = ''; } }
Objets en tant que type de données
Un autre aspect vraiment intéressant avec l’objet JavaScript est l’utilisation de type de données en « Table de hachage » (Hashmaps) et tout particulièrement sa façon de lier la valeur des propriétés avec une nomenclature littérale. À part quelques erreurs de l’interpréteur JavaScript (le nombre, le point flottant...), cette manière permet de passer en paramètre le nom des propriétés via une chaine de caractères comme le nom d’une variable. Encore mieux, passer une fonction dans une variable!
Des plus dynamique, et utilisée notamment pour produire un code simple et concis! Le format de stockage JSON dérivé du JavaScript est un bon exemple de la flexibilité de l’objet JavaScript.
À l’aide d’un objet littéral {} - il est possible de créer un objet simple. Ce nouvel objet hérite de l’Object.prototype et n’a pas de propriétés définies. Le constructeur Object crée une enveloppe pour représenter un objet. Il contient des paires de noms (des chaînes de caractères) et de valeurs (n’importe quelles valeurs), le nom est séparé de la valeur par deux points :. Si la valeur est null ou undefined, un objet vide sera créé et renvoyé. Sinon, un objet du type correspondant sera renvoyé.
var foo = {}; // un nouvel objet vide // un nouvel objet avec une propriété « test » avec la valeur 12 var bar = {test: 12};
Accès aux propriétés
Les propriétés d’un objet sont accessible de deux manières, via la notation par points ou la notation par crochet.
var foo = {name: 'Mon objet'} foo.name; // Mon objet foo['name']; // Mon objet var get = 'name'; foo[get]; // Mon objet foo.1234; // erreur de syntaxe (SyntaxError) foo['1234']; // fonctionne
Les notations fonctionnent de façon presque identique, la seule différence étant que la notation par crochet permet un ajustement dynamique des propriétés et l’utilisation de noms de propriétés qui conduiraient autrement à une erreur de syntaxe.
Les constructeurs JavaScript intégrés (Built-in) :
Tous les objets JavaScript héritent des propriétés et des méthodes de leur prototype. Les objets créés à l’aide d’un objet littéral, ou d’un nouvel objet « new Object() », héritent d’un prototype appelé Object.prototype tout en haut de la chaîne du prototype. Les objets créés avec new Date() héritent du Date.prototype, etc.
var oObjet1 = new Object(); // Un nouvel objet de type Object var oObjet2 = new String(); // Un nouvel objet de type String var oObjet3 = new Number(); // Un nouvel objet de type Number var oObjet4 = new Boolean(); // Un nouvel objet de type Boolean var oObjet5 = new Array(); // Un nouvel objet de type Array var oObjet6 = new RegExp(); // Un nouvel objet de type RegExp var oObjet7 = new Function(); // Un nouvel objet de type Function var oObjet8 = new Date(); // Un nouvel objet de type Date
// Exemples vides var oObjet = new Object(); var oObjet = new Object(undefined); var oObjet = new Object(null);
La déclaration d’un « prototypes »
var oPersonne = new Object({prenom:'Luc', nom:'Tremblay', age:50, groupesanguin:'AB'}) console.log(oPersonne.prenom+':'+oPersonne.nom); // Exemple multiple var oPersonne = new Object([{prenom:"Luc", nom:"Tremblay", age:50, groupesanguin:"AB"},{prenom:"Samuel", nom:"Rioux", age:40, groupesanguin:"A"}]) console.log(oPersonne[0].prenom+':'+oPersonne[0].nom); console.log(oPersonne[1].prenom+':'+oPersonne[1].nom);
Une simple fonction classique en guise de constructeur. Noter le mot-clé « new» déclaré à l’appel de la fonction.
function twPersonne() {} oPersonne = new twPersonne(); console.log(oPersonne.prenom); // undefined // Ajout d’une propriété twPersonne.prototype.prenom = null; console.log(oPersonne.prenom); // null oPersonne.prenom = "Luc"; console.log(oPersonne.prenom); // Luc
Exemple complet
function twPersonne(prenom_temp, nom_temp, age_temp, groupesanguin_temp) { this.prenom = prenom_temp; this.nom = nom_temp; this.age = age_temp; this.groupesanguin = groupesanguin_temp; } var oPersonne1 = new twPersonne("Luc", "Tremblay", 50, "O"); var oPersonne2 = new twPersonne("Samuel", "Rioux", 48, "B"); console.log(oPersonne1.prenom+':'+oPersonne1.nom); console.log(oPersonne2.prenom+':'+oPersonne2.nom);
Exemple dans un tableau
var oPersonnes = new Array(); oPersonnes.push(new twPersonne('Luc', 'Tremblay', 50, 'O')); oPersonnes.push(new twPersonne('Samuel', 'Rioux', 48, 'B')); for(var i in oPersonnes) { if (oPersonnes.hasOwnProperty(i)) { console.log(oPersonnes[i].prenom+' '+oPersonnes[i].nom); } }
Ajout d’une propriété à un objet
Une simple association :
oPersonne1.lieu = 'Ici';
Ajout d’une méthode à un objet
oPersonne1.complet = function () {
return this.prenom + ' ' + this.nom;
};
La propriété et la méthode seront ajoutées à oPersonne1 et à aucun autre objet.
La boucle « for in »
Tout comme l’opérateur « in », la boucle « for in » parcourt la chaîne des prototypes lors de l’itération sur les propriétés d’un objet. Mais attention, comme l’exemple suivant le démontre, notre prototype affiche aussi les propriétés de « Object.prototype » :
Object.prototype.age = 1; Object.prototype.groupesanguin = 12; var oPersonne1 = {prenom: 'Luc',nom: 'Tremblay'}; for(var i in oPersonne1) { // Affiche prenom, nom mais aussi age et groupesanguin! console.log('i:'+i); }
Utilisation de « hasOwnProperty » pour le filtrage
Cet exemple affiche seulement ses propres propriétés.
Object.prototype.age = 1; Object.prototype.groupesanguin = 12; var oPersonne1 = {prenom: 'Luc',nom: 'Tremblay'}; for(var i in oPersonne1) { if (oPersonne1.hasOwnProperty(i)) { // Affiche seulement prenom et nom, sans age ni groupesanguin. console.log('i:'+i); } }
Supprimer des propriétés
La seule façon de supprimer la propriété d’un objet est d’utiliser l’opérateur de suppression (delete). Modifier la propriété avec « undefined » ou « null » ne supprime que la valeur associée à la propriété, mais pas la clé.
var oPersonne1 = { prenom: 'Luc', nom: 'Tremblay', age: 1 }; oPersonne1.prenom = undefined; oPersonne1.nom = null; delete oPersonne1.age; for(var i in oPersonne1) { if (oPersonne1.hasOwnProperty(i)) { console.log(i, '' + oPersonne1[i]); } } // Résultat 1;undefined 2;null
Les sorties ci-dessus retournent à la fois « nom = indéfinie » et « prenom = null ».Il n’y a que la propriété « age » qui a été supprimée et donc absente de la sortie.
Héritage
Le prototype d’un objet est utilisé pour fournir de façon dynamique des propriétés aux objets qui héritent du prototype. L’exemple suivant démontre à merveille ce principe. L’objet « employe » hérite des propriété de l’objet « personne » en ajoutant « titre » tout en modifiant « salutation » :
var Personne = function(nom) { this.name = nom; this.peutParler = true; this.salutation = function() { if (this.peutParler) { console.log('Bonjour, je suis ' + this.nom); } }; }; var Employe = function(nom, titre) { this.nom = nom; this.titre = titre; this.salutation = function() { if (this.peutParler) { console.log('Bonjour, je suis ' + this.nom + ', le ' + this.titre); } }; }; Employe.prototype = new Personne(); var Client = function(nom) { this.nom = nom; }; Client.prototype = new Personne(); var luc = new Employe('Luc', 'bricoleur'); var pierre = new Client('Pierre'); var samuel = new Employe('Samuel', 'réparateur'); luc.salutation(); // Bonjour, je suis Luc, le bricoleur pierre.salutation(); // Bonjour, je suis Pierre samuel.salutation(); // Bonjour, je suis Samuel, le réparateur
Ajouter une propriété à un constructeur intégré
Même s’il n’est pas conseillé de modifier les constructeurs intégrés, l’exemple suivant ajoute une nouvelle propriété bien utile à l’objet date : ajouter un nombre de jours à une date.
Date.prototype.twAjouteJours = function(nJours) { this.setDate(this.getDate() + nJours); return this; };
Notation des clés
var test = { 'cas': 'Je suis un mot-clé, je dois donc être noté comme une chaîne', delete: 'Je suis un mot-clé, je dois donc' // génère une erreur de syntaxe (SyntaxError) };
Les propriétés d’objet peuvent être nommées à la fois en tant que caractères simples et en tant que chaines. En raison d’une autre erreur dans l’analyseur de JavaScript, ce qui précède génèrera une erreur de syntaxe avant le ECMAScript 5. Depuis ce dernier retourne « undefined ».
Cette erreur provient du fait que « delete » est un mot-clé; Par conséquent, il doit être notifié en tant que chaîne littérale pour s’assurer qu’il sera correctement interprété par les moteurs JavaScript plus anciens. Notez qu’en français, « supprimer » n’est pas pas un mot-clé! La solution suivante ne génère pas d’erreur :
var test = { 'cas': 'Je suis un mot-clé, je dois donc être noté comme une chaîne', supprimer: 'Je suis un mot-clé, je dois donc' // ne génère pas d'erreur de syntaxe };
Attention : littéraux numériques
Une idée fausse commune est que les littéraux numériques ne peuvent pas être utilisés comme des objets. En effet, un défaut de l’analyseur de JavaScript tente d’analyser la notation de point sur un nombre comme un littéral en virgule flottante.
2.toString(); // génère une erreur de syntaxe (SyntaxError)
Il y a quelques solutions de contournement qui peuvent être utilisées pour que les littéraux numériques agissent comme des objets aussi.
2..toString(); // le deuxième point est correctement reconnu 2 .toString(); // le point est correctement reconnu à cause de l’espace à gauche du point (2).toString(); // 2 est évalué en premier
Références
- Programmation orientée objet
- Table de hachage - Wikipedia.org
- MDN - Le modèle objet JavaScript en détails
- JSON - Introduction - w3schools
- JavaScript Garden
- Getting Started with JavaScript Objects - A Guide for Beginners
- What Exactly is a Class in Javascript?
- What is the Super keyword in JavaScript?
- What is the Super keyword in JavaScript?