@@
describes what's called a well-known symbol. (Note that it isn't actually valid syntax in JS.) According to the ES6/ES20151 specification:
Well-known symbols are built-in Symbol values that are explicitly referenced by algorithms of this specification. They are typically used as the keys of properties whose values serve as extension points of a specification algorithm. Unless otherwise specified, well-known symbols values are shared by all Code Realms (8.2).
Code Realms refer to different instances of a JavaScript environment. For example, the Code Realm of the root document would be different to that of JavaScript running in an <iframe>
.
An example of where it matter what code realm an object comes from is when trying to use instanceof
to determine whether an object is an array (hint: it won't work if it's from another frame). To avoid these kinds of issues from popping up with symbols, they are shared so that references to (say) @@toString
will work no matter where the object came from.
Some of these are exposed directly through the Symbol
constructor, for example, @@toPrimitive
is exposed as Symbol.toPrimitive
. That can be used to override the value produced when attempting to convert an object to a primitive value, for example:
let a = { [Symbol.toPrimitive]: () => 1 };
console.log(+a); // 1
console.log(a.valueOf()); // (the same object)
console.log(a.toString()); // "[object Object]"
In general, symbols are used to provide unique properties on an object which cannot collide with a random property name, for example:
let a = Symbol();
let foo = { [a]: 1 };
foo[a]; // 1
There is no way to access the value except by getting the symbol from somewhere (though you can get all symbols for an object by calling Object.getOwnPropertySymbols
, so they cannot be used to implement private properties or methods).
1: See this es-discuss topic for some discussion about the different names.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…