Les symboles sont une primitive relativement nouvelle introduite dans ES6. Une primitive de symbole représente une valeur unique qui n'entre jamais en collision avec une autre valeur, y compris celles d'autres primitives de symbole. Deux primitives de chaîne composées de caractères identiques sont considérées comme strictement égaux:
String() === String()
> true
String( "My string." ) === String( "My string." );
> true
Toutefois, deux symboles créés à l'aide de la fonction Symbol()
ne peuvent jamais être strictement égaux:
Symbol() === Symbol()
> false
Cette caractéristique vous permet d'utiliser des symboles comme clés de propriété uniques dans un objet, ce qui évite les conflits avec les clés que tout autre code pourrait ajouter à cet objet.
const mySymbol = Symbol( "Desc" );
const myObject = {
}
myObject
> Object { Symbol("Desc"): "propSymbol" }
Il existe trois types de symboles:
- Symboles créés avec
Symbol()
- Symboles partagés définis et récupérés à partir d'un registre de symboles global à l'aide de
Symbol.for()
- Les "symboles connus" sont définis comme des propriétés statiques de l'objet Symbol. Ces symboles contiennent des méthodes internes qui ne peuvent pas être écrasées accidentellement.
Symbol()
accepte une description (ou un "nom de symbole") comme argument facultatif.
Ces descriptions sont des libellés lisibles par l'humain à des fins de débogage. Elles n'affectent pas l'unicité du résultat. Tout appel à Symbol
renvoie une primitive de symbole complètement unique, même si plusieurs appels ont des descriptions identiques:
Symbol( "My symbol." ) === Symbol( "My symbol." );
> false
Comme pour les autres types de données primitifs, les symboles héritent des méthodes et des propriétés de leur prototype. Par exemple, vous pouvez accéder à une description en tant que propriété héritée du symbole créé:
let mySymbol = Symbol( "My symbol." );
mySymbol.description
> "My symbol."
Toutefois, vous ne pouvez pas créer de symbole à l'aide du mot clé new
:
let mySymbol = new Symbol();
> Uncaught TypeError: Symbol is not a constructor
Les symboles ne sont pas énumérables, ce qui signifie que les propriétés symboliques ne sont pas disponibles lorsque vous utilisez des méthodes standards pour les itérer. La méthode getOwnPropertySymbols()
permet d'accéder aux propriétés du symbole d'un objet.
Symboles partagés
La méthode Symbol.for()
tente de rechercher tous les symboles existants dans un registre de symboles global à l'échelle de l'environnement d'exécution avec une chaîne donnée comme clé et renvoie le symbole correspondant s'il en trouve un. Dans le cas contraire, il crée un symbole avec la clé spécifiée et l'ajoute au registre global:
let sharedSymbol = Symbol.for( "My key." );
sharedSymbol === Symbol.for( "My key." )
> true
Ces clés ne partagent aucun chevauchement fonctionnel avec les descriptions attribuées aux primitives Symbol
créées par l'auteur. Pour accéder à un symbole dans le registre de symboles, vous devez d'abord le créer à l'aide de for()
:
Symbol( "String" ) === Symbol( "String" );
> false
Symbol( "String" ) === Symbol().for( "String" );
> false
Symbol().for( "String" ) === Symbol().for( "String" );
> true
Pour récupérer la clé de n'importe quel symbole du registre de symboles, utilisez Symbol.keyFor()
:
let mySymbol = Symbol.for( "Key." );
Symbol.keyFor( mySymbol ) ;
> "Key."
Symboles connus
Les symboles connus sont des propriétés statiques de l'objet Symbol
, chacun étant un symbole lui-même. Les symboles connus fournissent des clés de propriété uniques pour accéder aux méthodes intégrées de JavaScript et les modifier, tout en évitant que le comportement principal ne soit écrasé par inadvertance.
Symbol;
> function Symbol()
asyncIterator: Symbol(Symbol.asyncIterator)
for: function for()
hasInstance: Symbol("Symbol.hasInstance")
isConcatSpreadable: Symbol("Symbol.isConcatSpreadable")
iterator: Symbol(Symbol.iterator)
keyFor: function keyFor()
length: 0
match: Symbol("Symbol.match")
matchAll: Symbol("Symbol.matchAll")
name: "Symbol"
prototype: Object { … }
replace: Symbol("Symbol.replace")
search: Symbol("Symbol.search")
species: Symbol("Symbol.species")
split: Symbol("Symbol.split")
toPrimitive: Symbol("Symbol.toPrimitive")
toStringTag: Symbol("Symbol.toStringTag")
unscopables: Symbol("Symbol.unscopables")
<prototype>: function ()
Les symboles étant une fonctionnalité spécifique à ES6, ces valeurs symboliques sont destinées à être utilisées comme des "points d'extension" pour les développeurs qui modifient le comportement de JavaScript sans introduire de problèmes de rétrocompatibilité.
Les valeurs de symbole connues sont souvent stylisées avec un préfixe @@
ou encapsulées dans %
pour différencier leurs clés de leurs prototypes modifiables. Par exemple, @@match
(ou %match%
) est une référence au Symbol.match
immuable, et non à String.prototype.match
.
Testez vos connaissances
Pouvez-vous utiliser new
pour créer un symbole ?
Lequel des énoncés suivants décrit des symboles « bien connus » ?