Symbols
c’est quoi?
La clé d’objet (object key
) est soit une chaîne de caractères, soit un type de données de Symbols
. Un Symbols
est un type de données primitives qui représente un identifiant unique sur un objet. Un symbole est une primitive qui ne peut pas être recréée. Dans ce cas, un symbole est similaire à un objet, car la création de plusieurs instances donnera des valeurs qui ne seront pas exactement égales. Mais un symbole est également une primitive en ce sens qu’il ne peut pas subir de mutation. Maintenant que nous savons un peu plus ce qu’est une valeur primitive, nous sommes enfin prêts à définir ce qu’est un Symbols
.
L’exemple ci-dessous montre comment créer un symbole :
const id = Symbol(); // id is a new symbol
L’exemple ci-dessus n’a pas de description ni de nom de symbole.
Pour créer un Symbols
avec une description, la syntaxe est présentée ci-dessous :
id = Symbol(description)
La syntaxe ci-dessus montre que nous pouvons obtenir une description des symboles.
Voir l’exemple ci-dessous :
const id = Symbol("tz94s"); console.log(id.description); //tz94s // or const id = Symbol("id");
Les symboles ayant la même description ne sont jamais les mêmes :
const id1 = Symbol("id"); const id2 = Symbol("id"); id1 === id2 // false
Nous pouvons convertir un symbole en une chaîne.
const id = Symbol("id"); const toStr = id.toString(); console.log( toStr, typeof toStr ); // Symbol(id) string
Propriétés cachées
L’objectif des symboles est de rendre un objet unique (cache les propriétés de l’objet) :
let identifier = Symbol("id");; const user = { name: "Bello", [identifier]: Symbol("Ja69xz") }; console.log( user[identifier] ); // Symbol(Ja69xz) console.log(user); // { name: 'Bello', [Symbol(id)]: Symbol(Ja69xz) }
Un identifiant unique peut également être ajouté à un objet déjà existant:
object[key] = description
Où key = Symbol(description)
const user = { name: "Bello" }; const id = Symbol("identifier"); user[id] = "Ja69xz"; console.log(user) // { name: 'Bello', [Symbol(identifier)]: 'Ja69xz' } console.log( user[id] ); // Ja69xz
L’avantage de l’utilisation d’un symbole dans un objet est qu’un tiers ne peut pas accéder au code de l’objet ni l’écraser.
L’avantage supplémentaire des symboles est qu’un objet peut avoir plus d’un identifiant.
Supposons qu’un script provenant d’une bibliothèque JavaScript ait son propre identifiant ajouté à l’objet unique créé :
let myId = Symbol("id"); const user = { // belongs to another code name: "Bello", [myId]: "Ja69xz" }; const scriptId = Symbol("identifier"); user[scriptId] = "sjz23f"; console.log(user); /* { name: 'Bello', [Symbol(id)]: 'Ja69xz', [Symbol(identifier)]: 'sjz23f' } */
Symboles d’objets ignorés dans un objet
Le passage en boucle d’un objet contenant l’identifiant Symbol
est toujours ignoré:
let myId = Symbol("id"); const user = { // belongs to another code name: "Bello", age: 27, [myId]: "Ja69xz" }; for (let key in user) { console.log(key) }; /* for (let value of Object.values(user)) { console.log(value); // Bello 27 } */
En revanche, Object.assign()
copie les propriétés des clés des chaînes et des symboles :
let myId = Symbol("id"); const user = { name: "Bello", age: 27, [myId]: "Ja69xz" }; let clone = Object.assign({}, user); console.log( clone[myId] ); // Ja69xz console.log(clone); // { name: 'Bello', age: 27, [Symbol(id)]: 'Ja69xz' }
L’exemple ci-dessous est réservé à un article distinct :
Object.keys(user); Object.values(user); Object.entries(user);
Symboles globaux
Les symboles ne sont jamais identiques par défaut, mais nous pouvons les rendre identiques dans un registre mondial de symboles. De plus, si un symbole n’existe pas, il peut être créé par la syntaxe ci-dessous.
Symbol.for(key)
Voir l’exemple ci-dessous :
// read from the global registry const id1 = Symbol.for("id"); const id2 = Symbol.for("id"); id1 === id2; // true
Les symboles à l’intérieur du registre sont appelés symboles globaux
Il y a aussi un revers qui renvoie un nom par un symbole global. Exemple
Symbol.keyFor(sym)
La syntaxe ci-dessus ne fonctionne pas pour les symboles non globaux.
Voir l’exemple ci-dessous :
const sym1 = Symbol.for("jx4i9"); const sym2 = Symbol.for("i2dwk"); // get name by symbol console.log( Symbol.keyFor(sym1) ); // jx4i9 console.log( Symbol.keyFor(sym2) ); // i2dwk
Si le symbole n’est pas global, il revient undefined
.
const globalSymbol = Symbol.for("jx4i9"); const localSymbol = Symbol("jx4i9"); console.log( Symbol.keyFor(globalSymbol) ); // jx4i9 => name, global symbol console.log( Symbol.keyFor(localSymbol) ); // undefined => not global
OK JavaScript Symbols
, mais pourquoi et comment ?
Les Symbols
ne garantissent pas une véritable confidentialité mais peuvent être utilisés pour séparer les propriétés publiques et internes des objets. Prenons un exemple où nous pouvons utiliser un symbole pour avoir des propriétés privées.
Prenons un exemple où la propriété d’un objet n’est pas privée.
var Pet = (function() { function Pet(type) { this.type = type; } Pet.prototype.getType = function() { return this.type; } return Pet; }()); var a = new Pet('dog'); console.log(a.getType());//Output: dog a.type = null; //Modified outside console.log(a.getType());//Output: null
Ci-dessus, le type
de propriété de la classe Pet
n’est pas privé. Pour la rendre privée, nous devons créer une fermeture. L’exemple ci-dessous illustre comment nous pouvons rendre le type
privé en utilisant une fermeture.
var Pet = (function() { function Pet(type) { this.getType = function(){ return type; }; } return Pet; }()); var b = new Pet('dog'); console.log(b.getType());//dog b.type = null; //Stays private console.log(b.getType());//dog
Inconvénient de l’approche ci-dessus : Nous introduisons une fermeture supplémentaire pour chaque instance Pet
créée, ce qui peut nuire aux performances.
Nous introduisons maintenant le Symbols
. Cela peut nous aider à rendre une propriété privée sans avoir recours à des fermetures supplémentaires inutiles. Exemple de code ci-dessous :
var Pet = (function() { var typeSymbol = Symbol('type'); function Pet(type) { this[typeSymbol] = type; } Pet.prototype.getType = function(){ return this[typeSymbol]; } return Pet; }()); var a = new Pet('dog'); console.log(a.getType());//Output: dog a.type = null; //Stays private console.log(a.getType());//Output: dog
Symboles du système
Il existe des propriétés que vous pouvez utiliser sur les Symbols
. On peut les utiliser pour modifier divers aspects des objets.
Consultez les propriétés statiques sur MDN
Nous utiliserons les propriétés de Symbols
dans les prochains articles.