[ES6] Symbol basic data type

Symbol - an identifier as an object property

8 data types:

  • 7 value types (basic data types): number, string, Boolean, null, undefined, symbol, bigint

  • 1 reference data type: Object

Symbol represents a unique value

A symbol value can be used as an identifier of an object attribute, which is the only purpose of this data type.

The Symbol value is generated by the Symbol function.

let s = Symbol();

typeof s; // "symbol"

Note that the new command cannot be used before the symbol function, otherwise an error will be reported. It is a string like data type. Symbol value is not an object, cannot add attribute.

The Symbol function can accept a string as a parameter to represent the description of the Symbol instance. This is just to make it easy to distinguish. If the parameter is an object, the toString() method of the object will be called to convert it into a string, and then a Symbol value will be generated.

let a = Symbol();
let b = Symbol();

console.log(a === b); // false (the parameter is just for better discrimination. Even if there is no parameter, the two return values are different, and the Symbol represents the unique value)

Symbol value cannot be calculated with other types of values, and an error will be reported.

let s = Symbol("My Symbol");

console.log(`your symbol is ${s}`); // report errors

Symbol values cannot be implicitly converted to strings, but can be explicitly converted. Symbol value can also be converted to Boolean, but cannot be converted to Number.

// Explicitly convert to string:
let s = Symbol("My Symbol");

String(s); // "Symbol(My Symbol)"

s.toString(); // "Symbol(My Symbol)"

// Explicit to Boolean:
let s2 = Symbol();

Boolean(s2); // true

console.log(!s2); // false

To read the description of the Symbol instance, you need to explicitly convert the Symbol into a string, or you can directly return the description of the Symbol through the instance attribute description.

const s = Symbol("This is a description");
console.log(s.description); // This is a description

The Symbol value can be used as an identifier for the property name of the object, so that the child can ensure that the property with the same name will not appear.

let mySymbol = Symbol();

// The first way to write
let a = {};
a[mySymbol] = 'Hello!';


// The second way to write
let a = {
  [mySymbol]: 'Hello!'
};

// The third way to write
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// The same result is obtained in the above writing
a[mySymbol] // "Hello!"

In the above code, the property name of the object is specified as a Symbol value through the square bracket structure and Object.defineProperty.

When Symbol value is used as object property name, dot operator cannot be used. When defining a property with a Symbol value inside an object (which is a public property), the Symbol value must be placed in square brackets.

const sym1 = Symbol();
const sym2 = Symbol();
let a = {};

// Case 1: use []
a[sym1] = "Hi"; // sym1 is placed in square brackets, and the attribute is defined by the Symbol value
console.log(a[sym1]); // Hi (there is an object attribute name sym1 defined by Symbol value in object a)
console.log(a.sym1); // undefined (attribute sym1 does not exist in object a)
console.log(a['sym1']); // undefined (attribute sym1 does not exist in object a)

// Case 2: use point operator
a.sym2 = "Hello"; // Sym2 after the dot operator exists with the string sym2 as the identifier instead of the previously defined Symbol value: sym2
console.log(a.sym2); // Hello (there is an attribute sym2 in object a with the value "hello")
console.log(a['sym2']); // Hello (there is an attribute sym2 in object a with the value "hello")
console.log(a[sym2]); // undefined (there is no object attribute name sym2 defined by Symbol value in object a)

In the above code, because the dot operator is always followed by a string identifier, sym2 after the dot operator exists as an object identifier rather than a Symbol value.

ergodic

Symbol is used as the property name. When traversing the object, the property will not appear in the for...in and for...of loops, nor will it be returned by Object.keys(), Object.getOwnPropertyNames(), JSON.stringify().

However, it is not a private property. There is an Object.getOwnPropertySymbols() method that can get all Symbol property names of the specified object. This method returns an array of all Symbol values of the current object used as property names.

The Reflect.ownKeys() method can return all types of key names, including regular key names and Symbol key names.

Since the Symbol value is used as the key name, it will not be traversed by the conventional method. We can use this feature to define some non private methods for objects, but we want to use them only internally.

Symbol.for()

Take a string as a parameter and search for a Symbol value with that parameter as its name. If yes, the Symbol value will be returned. Otherwise, a new Symbol value with the name of the string will be created and registered to the global.

let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');

console.log(s1 === s2); // true

In the above code, s1 and s2 are both Symbol values, but they are both generated by the Symbol.for method with the same parameter, so they are actually the same value.

The difference between Symbol and Symbol is that Symbol.for will be registered in the global environment for search, while Symbol will not.

Symbol.keyFor()

Returns the key of a registered Symbol type value.

let s1 = Symbol.for("foo");
Symbol.keyFor(s1); // "foo"

Built in Symbol value

Added by Jakebert on Thu, 04 Nov 2021 10:10:11 +0200