Symbole

Browser Support

  • Chrome: 38.
  • Edge: 12.
  • Firefox: 36.
  • Safari: 9.

Source

Une primitive de symbole représente une valeur unique qui ne se heurte jamais à une autre valeur, y compris la valeur d'autres primitives de symbole. Deux primitives de chaîne composées de caractères identiques sont évaluées comme strictement égales:

String() === String()
> true

String( "My string." ) === String( "My string." );
> true

Toutefois, aucun des deux symboles créés à l'aide de la fonction Symbol() ne peut jamais être strictement égal:

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 collisions avec les clés que tout autre code pourrait ajouter à cet objet.

const mySymbol = Symbol( "Desc" );

const myObject = {};
myObject[mySymbol] = "propSymbol";

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()
  • "Symboles connus" définis comme des propriétés statiques sur l'objet Symbol. Ces symboles contiennent des méthodes internes qui ne peuvent pas être écrasées accidentellement.

Symbol() accepte une description (ou "nom du 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 primitives, 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."

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 de 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 si un tel symbole est trouvé. Si elle n'en trouve pas, elle 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 se chevauchent pas fonctionnellement avec les descriptions attribuées aux primitives Symbol créées par l'auteur. Pour accéder à un symbole dans le Registre des 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 à partir du Registre des 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, qui sont eux-mêmes des symboles. 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 empêchant le comportement de base d'être é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 ()

Étant donné que les symboles sont une fonctionnalité propre à ES6, ces valeurs symboliques sont destinées à être utilisées comme "points d'extension" pour les développeurs qui modifient le comportement de JavaScript sans créer de problèmes de rétrocompatibilité.

Les valeurs de symboles 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%) fait référence à l'Symbol.match immuable, et non à String.prototype.match.

Vérifier vos connaissances

Pouvez-vous utiliser new pour créer un symbole ?

Oui
Non

Parmi les propositions suivantes, lesquelles décrivent des symboles "connus" ?

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