Represents a unique value. It is the seventh data type in JavaScript, with undefined, NULL, Boolean, String, Number, and Object being the first six.

Cause:

Object attribute names in ES5 are all strings, which can easily cause attribute name conflicts. When adding a new method to an existing object (mixin mode), the name of the new method may conflict with the existing method.

ES6 introduces Symbol to ensure that the name of each attribute is unique, thus fundamentally preventing attribute name conflicts.

The Symbol value is generated by the Symbol function (cannot be new)

You cannot use the new command before the Symbol function: Symbol is a primitive value, not an object, so you cannot add attributes, which is a data type similar to a string.

Property names of objects can now be of two types: an original string and a Symbol type.

let s = Symbol(a);typeof s
// "symbol"
Copy the code

Accepts a string as an argument that describes the Symbol instance

The Symbol function can take a string as an argument representing a description of the Symbol instance, mainly to make it easier to distinguish when displayed on the console or converted to a string.

let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 // Symbol(foo)
s2 // Symbol(bar)

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
Copy the code

In the code above, without arguments, they all output to the console as Symbol()

Symbol function of the same string argumentThe return values are not equal

The argument to the Symbol function only represents a description of the current Symbol value, so the return value of the Symbol function with the same argument is not equal

// No arguments
let s1 = Symbol(a);let s2 = Symbol(a); s1 === s2// false

// With parameters
let s1 = Symbol('foo');
let s2 = Symbol('foo');

s1 === s2 // false
Copy the code

Symbol takes an object, and the toString method of that object is called

If it has a toString method, call it. If it doesn’t, find Object.toString through the prototype chain

/ / itself
const obj = {
  toString() {
    return 'abc'; }};const sym = Symbol(obj);
console.log(sym) // Symbol(abc)


// It doesn't have one
const obj = {
    name:'aaa'
};
const sym = Symbol(obj);
console.log(sym)     //Symbol([object Object])
Copy the code

The Symbol value cannot be manipulated with other types of values

let sym = Symbol('My symbol');

"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string
Copy the code

Symbol values can be explicitly converted to strings, booleans (cannot be converted to other types)

// Turn to string
let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'

/ / a Boolean
let sym = Symbol(a);Boolean(sym) // true! sym// false

if (sym) {
  // ...
}

Number(sym) // TypeError
sym + 2 // TypeError
Copy the code

Symbol is used as the attribute name

let mySymbol = Symbol(a);// The first way
let a = {};
a[mySymbol] = 'Hello! ';

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

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

// All the above methods give the same result
a[mySymbol] // "Hello!"
Copy the code

The dot operator cannot be used when the Symbol value is the name of an object property

Because the dot operator is always followed by a string, the attribute name of A is actually a string, not a Symbol value.

const mySymbol = Symbol(a);const a = {};
a.mySymbol = 'Hello! ';
console.log(a[mySymbol]); // undefined
console.log(a['mySymbol']); // "Hello!"
console.log(a.mySymbol);  // "Hello!"

Copy the code

Inside an object, when defining a property using a Symbol value, the Symbol value must be placed in square brackets

let s = Symbol(a);let obj = {
  [s]: function (arg) {... }}; obj[s](123);

/ / short
letobj = { [s](arg) { ... }};Copy the code

Symbol attribute names the traversal of the Object. GetOwnPropertySymbols

Object. GetOwnPropertySymbols method returns an array, the member is the all of the current Object is used as the Symbol value of the property name.

const obj = {};
let a = Symbol('a');
let b = Symbol('b');

obj[a] = 'Hello';
obj[b] = 'World';

const objectSymbols = Object.getOwnPropertySymbols(obj);

objectSymbols
// [Symbol(a), Symbol(b)]
Copy the code

Object. GetOwnPropertySymbols method and the for… In circular Object. GetOwnPropertyNames method were compared

const obj = {};

let foo = Symbol("foo");

Object.defineProperty(obj, foo, {
  value: "foobar"});for (let i in obj) {
  console.log(i); / / no output
}

Object.getOwnPropertyNames(obj)
/ / []

Object.getOwnPropertySymbols(obj)
// [Symbol(foo)]
Copy the code

The reflect. ownKeys method can return key names of all types

let obj = {
  [Symbol('my_key')]: 1.enum: 2.nonEnum: 3
};

Reflect.ownKeys(obj)
// ["enum", "nonEnum", Symbol(my_key)]
Copy the code

Symbol. For (), (sets two symbols equal)

Reuse the same Symbol value (make two symbols equal)

It takes a string as an argument and searches for a Symbol value with that argument as its name. If so, return the Symbol, otherwise create and return a Symbol with the name of the string.

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

s1 === s2 // true



Copy the 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

Symbol.keyfor (), which returns the key of a registered Symbol type value

Returns the key of a registered Symbol type value

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

let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined
Copy the code