How much do you know about Symbol?

Keywords: Javascript

How much do you know about Symbol?

Symbol is the seventh type of JS data type. I've heard of undefined, null, Boolean, String, Number and Object, but is symbol a little strange? The emergence of symbol gracefully solves some basic problems, such as the confusion of references when large-scale projects cooperate with people.

1. How to generate a Symbol

The Symbol value is generated by the Symbol function:

let symbl = Symbol();
typeof symbl // "symbol"

From the above form, it is easy to conclude that there is no keyword new in the generation of Symbol, which means that it is an original data type.
It is actually a data type similar to a string. Is neither an object nor an array
When you declare, you enter or exit the parameter:

let symbl = Symbol('hello');
symbl.description // "hello"
//Symbol(hello)

The meaning of parameters is to make it easier for you to distinguish the current value.
In fact, the parameters of the Symbol function only represent the description of the current Symbol value.

let s1 = Symbol('2');
let s2 = Symbol('2');
s1 === s2 // false

Even without a description, the two values are not equal. This is somewhat similar to the object
a key:

Each Symbol is independent and unique.

2. Symbol usage and features

1. Symbol values cannot be evaluated with other types of values

 let sym = Symbol('1');
"2" + sym
// TypeError: can't convert symbol to string

but can be converted to Boolean values:

 let sym = Symbol('1');
 Boolean(sym) // true

2. How to prevent reference confusion

Due to the natural characteristics of Symbol, when it is used as the key value of attribute, the current key value pair can be tampered with.

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

but at this time, the. Operator will be invalid:

a.mySymbol;//undefined

Therefore, when declaring a symbol type inside an object, use [];

3. It will not be traversed by conventional loops

Loop methods that do not traverse symbol types are:
for...in,for...of,Object.keys(),Object.getOwnPropertyNames().
However: * * Reflect.ownKeys() * * exceptions:

let obj = {
  [Symbol('key')]: 1,
   name:'le'
};

Reflect.ownKeys(obj)
//  ["name", Symbol(key)]

4. Symbol.for() and Symbol.keyFor()

The above two methods seem to be related to traversal, but they have nothing to do with it.
1,Symbol.for()
Calling the method will return a Symbol value:

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

This is no different from Symbol().

Difference: Symbol.for() does not return a new value of Symbol type every time it is called. Instead, it checks whether the given key already exists. If it does not exist, a new value will be created

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

This means that the unique ID of Symbol.for() is the parameter.
2,Symbol.keyFor()

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

Obviously, Symbol.keyFor() serves Symbol.for(). Returns the key of a registered Symbol type value.

function foo() {
  return Symbol.for('bar');
}
const x = foo();
const y = Symbol.for('bar');
console.log(x === y); // true

Note: the name registered by Symbol.for() for the Symbol value is the name of the global environment, regardless of whether it is running in the global environment or not.

3. Several built-in properties

Originally intended to put this paragraph on it, but this is really important! The attributes on the Symbol can actually rewrite some operations of the target object. This level of modification should be the scope of metaprogramming.

1,Symbol.iterator

The Symbol.iterator property of the object, pointing to the default iterator method of the object.

The importance of this attribute is that es6 stipulates that the default iterator interface is deployed in the Symbol.iterator attribute of the data structure, or a data structure can be considered ergodic as long as it has the Symbol.iterator attribute.

var str = new String("hi");
[...str] // ["h", "i"]
str[Symbol.iterator] = function() {
  return {
    next: function() {
      if (this._first) {
        this._first = false;
        return { value: "bye", done: false };
      } else {
        return { done: true };
      }
    },
    _first: true
  };
};
[...str] // ["bye"]
str // "hi"

In fact, this has a lot to do with the generator. You can see here

2,Symbol.hasInstance

class MyClass {
  [Symbol.hasInstance](foo) {
    return foo instanceof Array;
  }
}
[1, 2, 3] instanceof new MyClass() // true

In the above code, MyClass is a class, and new MyClass() will return an instance. The Symbol.hasInstance method of this instance will be called automatically during instanceof operation to judge whether the operator on the left is an instance of Array.

3,Symbol.replace

const x = {};
x[Symbol.replace] = (...s) => console.log(s);

'Hello'.replace(x, 'World') // ["Hello", "World"]

When the replace method above takes effect, the modified function will be executed

Of course, there are many built-in attributes in Symbol. I'll introduce them again next time

Posted by Marijnn on Mon, 11 Oct 2021 20:06:53 -0700