JavaScript - Acquérir les fondamentaux (1/2)
Chapitre 5 - Introduction à la programmation orientée objet en JavaScript

Notion d'objet (les classes, l'héritage)

Plan de formation

Les objets ?

Définition

Les objets en JavaScript

Les objets en JavaScript sont proches de la notion de tableau.

var a = ["un", "deux", "trois"];
Exemple de tableau
Key Value
0 un
1 deux
2 trois
var personne = {
	nom: "DURAND",
	prenom: "Robert"
};
Exemple d'objet
Key Value
nom DURAND
prenom Robert

Tableau indexé et tableau associatif

Il existe deux sortes de tableaux :

JavaScript utilise les objets pour implémenter les tableaux associatifs.

Créer et utiliser des objets

Structure d'un objet

Les objets sont constitués de propriétés (valeurs associées à des noms) et de méthodes (fonctions associées à l'objet).
Exemple :

var personne = {
	nom: "DURAND",
	prenom: "Robert",
	direBonjour: function () {
		console.log("Bonjour");
	}
};

personne.direBonjour();

Création différée d'un objet

JavaScript st un langage dynamique qui permet la modification d'un objet après sa création !

var personne = {};
personne.nom = "DURAND";
personne.prenom = "Robert";
personne.direBonjour = function () {
	console.log("Bonjour");
}

personne.direBonjour();

La valeur this

Un autre élément important à prendre en compte est que l'objet doit avoir conscience de lui-même. L'objet peut évoquer des propriétés et des méthodes qui lui appartiennent.

Important :
this est un mot clefs réservé JavaScript qui va permettre de représenter l'objet courant, c'est une référence à l'objet courant avec lequel on est entrain de travailler.

var personne = {
	nom: "DURAND",
	prenom: "Robert",
	afficheNom: function () {
		console.log("nom : " + this.nom);
	}
}

personne.afficheNom();

La fonction this a permis de récupérer les propriétés de l'objet.

Les constructeurs

Utiliser une fonction pour créer un objet.

function Personne() {
	this.nom = "DURAND";
	this.prenom = "Robert";
}

var personne = new Personne();
console.log(personne.nom)

Utiliser une fonction et passer des paramètres pour créer un objet

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

var nom_personne = "DURAND";
var prenom_personne = "Robert";
var personne = new Personne(nom_personne, prenom_personne);
console.log(personne.nom)

Exercice pratique : Constructeurs

var Personne = function (p_nom, p_prenom) {
	this.nom = p_nom
	this.prenom = p_prenom
	this.afficheNom = function () {
		console.log("nom : " + this.nom);
	}
};

var p = new Personne("DURAND", "Robert")
p.afficheNom();

L'opérateur instanceof

Avec une variable primitive, il est possible d'utiliser typeof afin de connaître le type de la variable. Avec un objet, il faut utiliser instanceof afin de tester le constructeur de l'objet.

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

var nom_personne = "DURAND";
var prenom_personne = "Robert";
var personne = new Personne(nom_personne, prenom_personne);
console.log(personne.nom);

console.log(personne instanceof Personne ? "oui" : "non");

L'objet Object

Object est l'objet de base implémenté par l'ensemble des objets JavaScript.

var obj = {};
var obj = new Object();

Autrement dit, tous les objets JavaScript héritent de Object.
Ils bénéficient des méthodes de Object :

Définition héritage

En programmation orientée objet, l'héritage est un mécanisme qui permet à une classe (appelée classe dérivée ou enfant) de récupérer les propriétés et méthodes d'une autre classe (appelée classe de base ou parent). Cela favorise la réutilisation du code et permet de créer des structures hiérarchiques où les objets enfants peuvent étendre ou spécialiser le comportement de leurs parents.

Notion de prototype

Plan de formation

Qu'est-ce qu'un prototype ?

Définition d'un prototype de Wikipedia

JavaScript est un langage orienté objet à prototype, c'est-à-dire que les bases du langage et ses principales interfaces sont fournies par des objets qui ne sont pas des instances de classes, mais qui sont chacun équipés de constructeurs permettant de créer leurs propriétés, et notamment une propriété de prototypage qui permet d'en créer des objets héritiers personnalisés.

Qu'est-ce qu'un prototype ?

Les fonctions sont des objets qui ont des propriétés. Une de ces propriété est le prototype. Il est possible d'ajouter des propriétés et méthodes à partir du prototype.

Ajouter des propriétés à un prototype

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

Personne.prototype.age = 30;
Personne.prototype.getAge = function () {
	return this.age;
}

var personne = new Personne("DURAND", "Robert");
console.log(personne.getAge());

En JavaScript, les objets sont passés par référence. C'est-à-dire qu'il y a qu'UN seul prototype pour tous les objets du même constructeur.

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

Personne.prototype.age = 30;
Personne.prototype.getAge = function () {
	return this.age;
}

var personne = new Personne("DURAND", "Robert");
console.log(personne.getAge());
var personne2 = new Personne("Durand", "ROBERT")
console.log(personne2.getAge());
Personne.prototype.age = 130;
console.log(personne.getAge());
console.log(personne2.getAge());

Exercice pratique - Prototype

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

Personne.prototype.age = 30;
Personne.prototype.getAge = function () {
	return this.age;
}

var p = new Personne("DURAND", "Robert");
var p2 = new Personne("ALBERT", "Toto");
Personne.prototype.age = 130;
console.log(p.getAge());
console.log(p2.getAge());

Comme on peut le constater, l'âge a été redéfini à 130. La sortie console montre bien 2x 130 et non 1x 30 et 1x 130.

Distinguer les propriétés d'un objet et celles de son prototype

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

Personne.prototype.age = 30;
var personne = new Personne("DURAND", "Robert");
console.log(personne.age);
console.log(personne.constructor.prototype.age);

Dans cette exemple ci-dessus, le nom et le prénom sont des propriétés de l'objet. Quant à l'âge, c'est une propriété du prototype de "Personne".

Améliorer les objets JavaScript (Array,...)

Array.prototype.showAll = function () {
	for (var i = 0; i < this.length; i++) {
		console.log(this[i]);
	}
};

var arr = ["un", "deux", "trois"];
arr.showAll();

Comme le montre l'exemple, il est facile d'améliorer des objets existants avec des fonctions/méthodes supplémentaires. Cependant, l'exemple est déconseillé par github Copilot car cela va avoir un impact sur tout le projet. Donc attention.

Notion de design patterns

Plan de formation

Les Design Patterns : un problème, une solution

Les Design Patterns sont décrits dans un livre :
Catalogue de modèles de conception réutilisable écrit par 4 auteurs ce qui lui a valu le nom de Le Gof book (Gang of four).
Les auteurs sont :

Ce livre contient différents problèmes du monde de l'informatique avec des solutions.

Le pattern Module

Le pattern Module a été conçu à l'origine pour permettre l'encapsulation (private et public). En JavaScript, ce pattern est utilisé pour simuler le comportement d'une classe.

Le problème de base est la portée des variables et l'on souhaite limiter leur portée en encapsulant les variables et les propriétés dans un module qui pourra être réutilisé plus tard.

Le pattern Module - fonction auto-appelante

(function sayHello() {
	console.log("Hello");
})();

Les fonctions auto-appelante sont cloisonnées dans leur bloc de code ce qui limite leur portée. Les parenthèses ouvrante et fermante à la fin du bloc de code déclenche l'appel de la fonction.

Le pattern Module - l'implémentation

var monModule = (function () {
	var compteur = 0;
	return {
		incrementCompteur: function () {
			return compteur++;
		}
	}
})();

var i = monModule.incrementCompteur();
console.log(i);
i = monModule.incrementCompteur();
console.log(i);

Le pattern Singleton

Le pattern Singleton permet de récupérer seulement un objet à partir d'un constructeur.

var monSingleton = (function () {
	var instance;
	function init() {
		// Singleton
		var hello = "Hello " + Math.random();
		return {
			sayHello: function () {
				console.log(hello);
			}
		};
	}

	return {
		getInstance: function () {
			if (!instance) {
				instance = init();
			}
			return instance
		}
	}
})();

var s = monSingleton.getInstance();
var s2 = monSingleton.getInstance();
s.sayHello();
s2.sayHello();