es5-objets.png

ES5 - Les objets

par Romain · · pas de commentaire

Rappel ES5 - Les objets

Dans une volonté d'en apprendre plus sur javascript, bien souvent nous partons sur l'apprentissage d'un nouveau framework, ces frameworks souvent accompagnés de cli permettent directement de pouvoir travailler en EcmaScript 2015+ (à travers babel) afin d'obtenir des applications "modernes".

Cependant, je remarque que la plupart du temps il est facile d'appliquer des principes et d'effectuer des tâches en javascript sans pour autant comprendre ce qu'il se passe sous le capot, d'autre part dans un cadre pédagogique où l'on souhaiterait enseigner ces nouveaux concepts à des personnes qui ont pratiqués du javascript à l'ancienne, il est bien difficile de pouvoir créer des analogies si les concepts ES5 sont inconnus.

Cet article est le premier d'une longue série afin de faire une piqure de rappel sur l'ancienne syntaxe de javascript que l'on appelle ES5 et qui a mon sens il est important de maitriser.

Créer un objet

La déclaration littéral

on peut déclarer un objet de manière littéral :

"use strict";

var personne = {
  nom: "Doe",
  prenom: "John",
};
personne.age = 14;

On peut aisément, et dynamiquement modifier la nature d'un objet à la volée. Cependant cela manque de structure, des fois pour faire une application web de plus grande envergure il sera nécessaire de structurer notre objet avant utilisation et pour cela nous allons déclarer l'objet différemment.

La déclaration d'un objet à travers la fonction Constructeur

Nous allons cette fois-ci, créer ce que l'on appelle une fonction Constructeur, cette fonction va permettre de définir les champs que possède notre objet et eventuellement leur associer des valeurs.

Pour réaliser cela il faut suivre une convention de nommage, à savoir il faut mettre une majuscule à la fonction

/**
 * Appelé avec le mot clé "new",
 * Ce constructeur permet de créer une nouvelle personne john doe.
 * @constructs
 * */
function Personne() {
  this.nom = "Doe";
  this.prenom = "John";
}

Une fois cette fonction écrite, nous pouvons l'utiliser pour créer notre objet, pour cela il faudra utiliser le mot clé new

/**
 * Appelé avec le mot clé "new",
 * Ce constructeur permet de créer une nouvelle personne john doe.
 * @constructs
 * */
function Personne() {
  this.nom = "Doe";
  this.prenom = "John";
}

// j'instancie (je créer) une nouvelle personne john doe
var john = new Personne();
console.warn(john);

Vous allez me dire , ok très bien mais quel est l'intêret de ce constructeur ?

Sur cet exemple le constructeur va toujours créer une personne s'appelant john doe, ce qui présente peut d'intêret dans notre cas. Il est possible de pouvoir paramétrer dynamiquement les champs de notre objet lors de l'appel au constructeur.

Dans le cas suivant je vais créer un constructeur me permettant de pouvoir ajouter lors de la création de mon objet personne les valeurs des champs "nom" et "prenom"

/**
 * Appelé avec le mot clé "new",
 * Ce constructeur permet de créer une nouvelle personne.
 * @constructs
 * @param { String } nom
 * @param { String } prenom
 * */
function Personne(nom, prenom) {
  this.nom = nom;
  this.prenom = prenom;
}

// j'instancie (je créer) une nouvelle personne john doe
var premierePersonne = new Personne("john", "doe");

// j'instancie (je créer) une nouvelle personne romain barraud
var deuxiemePersonne = new Personne("romain", "barraud");
// affichage de john
console.warn(premierePersonne);
// affichage de romain
console.warn(deuxiemePersonne);

Et que se passe t'il si je n'utilise pas le mot clé new ?

Si on ne déclarait pas avec new, alors nous obtiendront le retour de la fonction Personne, Attention toutefois, cela signifie que le mot clé this correspond à la portée window, par conséquent les variables nom et prenom seraient déclarées dans window.

/**
 * Appelé avec le mot clé "new",
 * Ce constructeur permet de créer une nouvelle personne.
 * @constructs
 * @param { String } nom
 * @param { String } prenom
 * */
function Personne(nom, prenom) {
  this.nom = nom;
  this.prenom = prenom;
}

// sans mot clé new :(
var romain = Personne("barraud", "romain");

console.log(romain); // undefined (retour de la fonction void)
console.log(window.nom); // barraud
console.log(window.prenom); // romain

Object.create() pour créer un objet

Les deux façons de créer un objet que nous venons de voir, permettent facilement de créer des objets il existe bien evidemment une façon plus complète mais aussi plus difficile à lire, la voici

var romain = Object.create(Object.prototype, {
  nom: {
    value: "Barraud",
    enumerable: true,
    writable: true,
    configurable: true,
  },
  prenom: {
    value: "Romain",
    enumerable: true,
    writable: true,
    configurable: true,
  },
});

console.log(romain);

En utilisant la function object.create à laquelle on fournit le prototype de Object qui va devenir le prototype de cette function.

Attention on reviendra plus tard sur cette notion de prototypes

Ensuite on va créer nos champs dans l'objet , vous remarquerez qu'elles sont plus verbeuse car chaque champs possède en réalité une valeur mais aussi trois property descriptor :

  • enumerable
  • writable
  • configurable

Lors de la déclaration d'un objet litéral ou par constructeur on ne spécifie pas ces trois descriptors, par simplicité ils sont automatiquement mis à true comme le code présenté ci-dessus.

Maintenant on peut remercier les deux syntaxes précedentes pour ne pas a avoir à écrire ceci à chaque fois.

Créer un objet avec les classes ES2015 +

Bon ok cet article devait être reservé à ES5... Toutefois je trouve interessant de rappeler la syntaxe que l'on rencontrera le plus dans les projets et ainsi pouvoir comparer avec celles de ES5

"use strict";

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

  parler() {
    console.log("Hourra ça marche en prod");
  }
}

var romain = new Personne("Romain", "Barraud");
romain.parler();
console.log(romain);

C'est plus traditionnel et cela ressemble aux langages fortement typés comme java et c'est certainement de cette manière que vous coderez vos objets dans vos projets. Cependant il faut garder en tête que ce n'est qu'une astuce visuelle du langage.

Accèder aux champs/propriétés d'un objet

Accéder aux propriétés

J'ai maintenant réussi à créer un objet en javascript, maintenant ce qui m'interesse c'est de pouvoir récupérer certaines valeurs que possèdent les propriétés de mon objet. Pour cela il existe plusieurs notations différentes

  • objet[propriete]
  • objet.propriete
"use strict";

var personne1 = {
  nom: "Barraud",
  prenom: "Romain",
};

console.log(personne1.prenom); // affiche "romain"
console.log(personne1["romain"]); // résultat identique mais avec des brackets

Dans cette deuxième notation on va chercher la valeur de la propriété avec une chaine de caractère, cette chaîne de caractère pourrait être dans une variable et cette variable pourrait être renseignée par l'utilisateur par exemple.

var personne1 = {
  nom: "Barraud",
  prenom: "Romain",
};

let nomDuChampsCible = "prenom";

console.log(personne1[nomDuChampsCible]); // Romain
nomDuChampsCible = "nom";
console.log(personne1[nomDuChampsCible]); // Barraud

Utiliser les getters et setters

Comment faire des getters et setters en javascript et à quoi ça sert?

Déclarer un accesseur Get

Lorsque l'on créer un objet il est possible de lier une de ses propriétés à une fonction lors de l'accès a cette même propriété.

// code code va ajouter une pseudo-propriété (un accesseur) fullName
var personne1 = {
  nom: "Barraud",
  prenom: "Romain",
  get fullName() {
    return this.prenom + " " + this.nom;
  },
};

console.warn(personne1.fullName); // Romain Barraud

Il est intéressant de noter que réaffecter fullName ne fonctionne pas et cela est normal car aucun Setter n'est défini pour cette pseudo-propriété

var personne1 = {
  nom: "Barraud",
  prenom: "Romain",
  get fullName() {
    return this.prenom + " " + this.nom;
  },
};

personne1.fullName = "Jean Valjean";
console.warn(personne1.fullName); // Romain Barraud

Ajouter un accesseur Get sur un objet existant

"use strict";

var personne1 = {
  nom: "Barraud",
  prenom: "Romain",
};

Object.defineProperty(personne1, "fullName", {
  get: function () {
    return this.prenom + " " + this.nom;
  },
});

console.warn(personne1.fullName);

Supprimer un accesseur Get

delete personne1.fullName;

Déclarer un Setter

Il est possible de lier à une propriété une function qui sera executé à chaque tentative de modification de celle-ci Dans l'exemple suivant, je montre comment à partir du fullName je vais alimenter le nom et prenom

var personne1 = {
  nom: "Barraud",
  prenom: "Romain",
};

Object.defineProperty(personne1, "fullName", {
  get: function () {
    return this.prenom + " " + this.nom;
  },

  set: function (value) {
    var noms = value.split(" ");
    this.prenom = noms[0];
    this.nom = noms[1];
  },
});

personne1.fullName = "Jean Valjean";

console.log(personne1.fullName);
console.log(personne1.prenom);
console.log(personne1.nom);

Pour ce qui est de la suppression on fera la même chose que pour le getter

Voilà pour le petit topo sur les objets en javascript, si vous souhaitez aller plus loin voici une liste d'articles connexes: