Import et export
Depuis ES6, on peut gérer les dépendances entre fichiers avec les mots clés "import" et "export"
Ex
export default class Person { constructor(name) { this.name = name; } present() { console.log("hello, I'm " + this.name); } }
De cette façon, dans un autre script, on pourra avoir :
import Person from "./Person.js"; const p = new Person("Bob")
Attention, il faudra penser à appeler votre js en utilisant l'attribut type="module"
<script type="module" src="test.10-module.js">
Objet décomposé (Object Destructuring)
L'object destructuring existe depuis ECMAScript 6 (2015).
La façon classique de récupérer les propriétés de l'objet p quand p = {nom:"Dylan", prenom:"Bob"} :
const nom = p.nom; const prenom = p.prenom;
Une syntaxe plus courte existe :
const {nom, prenom} = p;
Si les noms des variables sont déjà utilisés :
const {nom:n, prenom:p} = p;
spread operator pour "étaler" vos objets et tableaux
Depuis ES2015, on peut utiliser une nouvelle syntaxe, le spread operator, qui permet de copier et "d'étaler" des objets lors de l'assignation.
Ex :
const bob = { firstname: "Bob" } const bobDylan = { ...bob, lastname: "Dylan" }; console.log(`bobDylan`, bobDylan);
Attention il ne faut pas confondre le rest operator avec le spread operator même s'ils se ressemblent beaucoup.
L'opérateur spread permet de cloner facilement un objet (shallow copy) :
const bob = { name: "Bob" }; const bobbis = { ... bob}; console.log(bobbis);// copie de l'objet bob attendue
L'opérateur spread permet également d'étendre un itérable (par exemple une expression de tableau ou une chaîne de caractères) en lieu et place de plusieurs arguments (pour les appels de fonctions) ou de plusieurs éléments (pour les littéraux de tableaux) ou de paires clés-valeurs (pour les littéraux d'objets).
Assignation destructurée avec le rest operator
Depuis ES2015, on peut utiliser une nouvelle syntaxe, le rest operator (...), soit pour récupérer des arguments d'une fonction, soit pour les assignations destructurées :
const fruits = ["Banane", "Cerise", "Pomme"]; const [banane, ...otherFruits] = fruits; console.log(`banane`, banane); console.log(`otherFruits`, otherFruits);
Attention il ne faut pas confondre le rest operator avec le spread operator même s'ils se ressemblent beaucoup.
Raccourci pour la création d'objets - depuis ES2015
Lorsque la propriété de l'objet que l'on veut créer a le même nom que la variable utilisée pour valeur, on peut utiliser un raccourci :
function createPerson() { const name = 'bob'; return { name }; }
Depuis ECMAScript 2020 (ES11), il est possible de gérer des propriétés privées avec getter et setter.
Références :
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
Exemple :
class Person { #name; constructor(name) { this.#name = name; } get name() { return this.#name; } set name(new_name) { this.#name = new_name; } } const b = new Person("Bob"); console.log(b.name); b.name = "toto"; console.log(b.name);
10. Propriétés et méthodes de classe avec le mot clé static
cf : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Classes/static
Le mot-clé static permet de définir une propriété statique d'une classe. Les propriétés statiques ne sont pas disponibles sur les instances d'une classe mais sont appelées sur la classe elle-même. Les méthodes statiques sont généralement des fonctions utilitaires (qui peuvent permettre de créer ou de cloner des objets par exemple).
Littéraux de gabarit ou "template string"
Les littéraux de gabarits sont des littéraux de chaînes de caractères permettant d'intégrer des expressions, c'est-à-dire tout ce qui retourne une valeur.
L'usage de base consiste à imbriquer des variables dans les chaînes, entre ${ et }. Elles se verront "remplacées" par leur valeur au moment de l'exécution.
let nb_kiwis = 3; const message = `J'ai ${nb_kiwis} kiwis dans mon panier`; // Résultat : J'ai 3 kiwis dans mon panier
Fonction de tag
Ces fonctions recoivent séparément les parties dynamiques et statiques des "template string". Au développeur d'en faire ce qu'il veut !
Imaginons, par exemple, que nous ayons besoin d'une fonction qui mette la première lettre en Majuscule de toutes les parties dynamiques :
const p1 = "josé"; const p2 = "simone"; const p3 = "pedro"; // fonction de tag const uppercaseFirstLetter = (strings, ...values) => { // strings est un tableau composées des parties statiques // values est un tableau avec les expressions à évaluer const names = values.map( (name) => name.charAt(0).toUpperCase() + name.slice(1) ); // Merge des tableaux strings et names return strings .map((string, i) => `${string}${names[i] ? names[i] : ""}`) .join(""); }; // Appel de la fonctin de tag const result = uppercaseFirstLetter`Ce WE, je suis allé à la fête des fanfares avec ${p1}, ${p2} et ${p3}.`; console.log(result);
Composants
Le but des composants est de fournir du code réutilisable et encapsulé directement utilisable comme une balise HTML classique.
Attention, ce n'est pas encore une norme et bon nombre de navigateurs n'interprèteront pas correctement le code ci-dessous qui repose sur 3 mécanismes :
Custom Element
Exemple de déclaration d'un élément Custom :
export default class DigiCardComponent extends HTMLElement { constructor(){ super(); console.log(`Dans le constructeur de la carte`); } /** * Appelé quand le composant est inséré */ connectedCallback() { this.innerHTML = `<h2>Inventeur du web ?</h2>` } } customElements.define('digi-card', DigiCardComponent);
Shadow DOM
Le problème dans l'exemple précédent, c'est que le contenu peut à tout moment être modifié par un script js.
Pour remédier à cela, on fait appel au "shadow DOM" :
export default class DigiCardComponent extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); const question = document.createElement('h2'); question.textContent = 'Inventeur du web ?'; shadow.appendChild(question); console.log(`Dans le constructeur de la carte`); } } customElements.define('digi-card', DigiCardComponent);
Si on inspecte le code, on voit l'expression #shadow-root (open) qui indique que le "shadow DOM" fait bien office de barrière infranchissable.
Template
La balise <template> peut être directement utilisée dans un document HTML mais elle n'est pas affichée et rien de ce qui est déclaré à l'intérieur ne sera interprété par le navigateur. Pour que la balise template soit utilisable, Il faudra utiliser js en la clonant.
Ex de template dans le HTML :
<template id="card-template"> <h2>Inventeur du web ?</h2> <h3>Tim Berners-Lee</h3> </template>
... que l'on peut utilser dans le shadowDOM :
export default class DigiCardComponent extends HTMLElement {
constructor() {
super();
const template = document.querySelector('#card-template');
const clonedTemplate = document.importNode(template.content, true);
const shadow = this.attachShadow({ mode: 'open' });
shadow.appendChild(clonedTemplate);
console.log(`Dans le constructeur de la carte`);
}
}
customElements.define('digi-card', DigiCardComponent);
Les limites des web components
Les web components n'étant pas supporté par tous les navigateurs, il existe le "polyfill" web-component.js pour s'assurer du bon fonctionnement.