Symbole

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 ?

Non
Oui

Lequel des énoncés suivants décrit des symboles « bien connus » ?

Propriétés statiques de l'objet "Symbol"
Symboles que vous utilisez fréquemment
Des clés de propriété uniques pour accéder aux méthodes intégrées de JavaScript et les modifier