To tell you the truth, I really admired the type of Symbol at the moment I finished writing this article. I didn’t use this data type usually, and I never thought I would use it. Before that, I just knew this word and realized its power after I finished writing it.

Symbol is a new data type in ES6. Why did we add this data type? At the beginning of an interviewer so asked me, I was young and frivolous, the OS of the heart is, I do not know ๐Ÿคฃ! We’re still not familiar with the data type Symbol.

Prior to ES6, object keys could only be string types. However, there was a problem with this. This would cause a key name conflict, which would override the former.

1, concept,

Symbol is a basic data type. The symbol () function returns a value of type symbol, which has static properties and static methods. But it is not a constructor and cannot be created using new Symbol().

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

When a Symbol is used as an object attribute, it must be enclosed in square brackets when inside the object. Any Symbol that is not enclosed in square brackets represents a string.

let s = Symbol(a);let obj = {
  [s]: "Jack".};
obj[s]; // "Jack"
obj.s; // undefined Copy the code

And when you want to take the value of this property, you can’t use the dot operator, because the dot operator is also followed by a string type.

When a Symbol data type is created, it is created as a Symbol(). When printed, it is created as a Symbol(), making it difficult to distinguish the meaning of each Symbol type. So we can take a string argument to the Symbol function that represents the description of the variable that defines the Symbol type.

let s1 = Symbol("a");
console.log(s1); // Symbol(a)
s1.toString(); // "Symbol(a)"
Copy the code

If the Symbol type receives an object type, its internal toString method is called to change it to a string before a Symbol value is generated.

let arr = [1.2.3];
let s1 = Symbol(arr);
console.log(s1); / / Symbol (1, 2, 3)
let obj = {
  toString: (a)= > "abc".}; let s2 = Symbol(obj); console.log(s2); // Symbol(abc) Copy the code

Variables of type Symbol cannot be evaluated with other variables, and can only be converted to strings or Boolean types.

let s = Symbol(a);console.log("1" + s); // TypeError: Cannot convert a Symbol value to a string
s.toString(); // "Symbol()"
Boolean(s); // true
Number(s); // TypeError: Cannot convert a Symbol value to a number
Copy the code

2, Symbol. The prototype. The description

When add description to Symbol by Symbol. The prototype. The description for the description.

let s = Symbol("Jack");
s.description; // 'Jack'
Copy the code

3, Symbol. For(key) and Symbol. KeyFor (SYM)

When I first saw these two methods, I thought they were two traversal methods ๐Ÿ˜….

  1. Symbol. For (key) : Searches for an existing Symbol using the given key and returns the Symbol if found. Otherwise, a new symbol is created in the global symbol registry with the given key.
  2. Symbol.keyfor (SYM) : Retries a key from the global Symbol registry for a given Symbol.
let s1 = Symbol.for("foo");
let s2 = Symbol.for("foo");
s1 === s2; // true
Copy the code

Symbol. For searches for Symbol values with this parameter as the name. If so, return the Symbol value, otherwise create a new Symbol with the string name and register it globally. So the values of the two identical descriptions created by it will be equal. This creation has a different result than the normal Symbol() :

let s1 = Symbol("foo");
let s2 = Symbol("foo");
s1 === s2; // false
Copy the code

Symbol() returns a new value anyway. In other words, the value generated by Symbol() is not registered in the global, so the value returned is new. Symbol.for() first looks up the global, returns the value if it has one.

Symbol.keyfor (SYM) is a global lookup to see if the Symbol value exists, and if so, returns the description.

let s1 = Symbol.for("Jack");
Symbol.keyFor(s1); // 'Jack'
let s2 = Symbol("Rose");
Symbol.keyFor(s2); // undefined
Copy the code

Because S2 is not mounted globally, symbol.keyfor () cannot find it and returns undefined.

4. Built-in Symbol attribute

In addition to defining its own Symbol values, ES6 also provides 13 (and possibly more in the future ๐Ÿ˜›) built-in Symbol values that point to methods used within the language.

4.1 Symbol. AsyncIterator

AsyncIterator specifies the default asynchronous iterator for an object. If an object has this property set, it is an asynchronous iterable and can be used for await… Of circulation. In other words, an asynchronous iterable must have a Symbol. AsyncIterator property inside it.

const myAsyncIterable = new Object(a);myAsyncIterable[Symbol.asyncIterator] = async function* () {
  yield "hello";
  yield "async";
  yield "iteration!";
};  (async () = > {  for await (const x of myAsyncIterable) {  console.log(x);  // expected output:  // "hello"  // "async"  // "iteration!"  } }) ();Copy the code

When executing for await… Of, the value of the Symbol. AsyncIterator property in the variable is executed.

4.2, Symbol. HasInstance

Symbol. HasInstance is used to determine whether an object is an instance of a constructor. So you can use it to customize the behavior of the instanceof operator on a class. In other words, when determining whether an instance is an instance of a class, the Symbol. HasInstance attribute of that class is executed.

class Fu {
  [Symbol.hasInstance](num) {
    return num === 1;
1 instanceof new Fu(); // true 2 instanceof new Fu(); // false Copy the code

4.3, Symbol. IsConcatSpreadable

Built-in Symbol. IsConcatSpreadable Symbol is used to configure a particular object as an Array. The prototype. The concat () method whether the parameters of the Array elements.

// By default
let arr = [1.2.3];
let brr = [4.5.6];
arr.concat(brr); // [1, 2, 3, 4, 5, 6]
/ / set the Symbol. After isConcatSpreadable
let arr = [1.2.3]; let brr = [4.5.6]; brr[Symbol.isConcatSpreadable] = false; arr.concat(brr); // [1, 2, 3, [4, 5, 6]] Copy the code

Array of Symbol. IsConcatSpreadable attribute is set to false, use the concat method when the data is not carried out.

Default array concat method used for class array, the array is not, we can give our class array Symbol. IsConcatSpreadable set to true, so that it can be opened, and completed the class array is converted to an array, so one more turn class array array method.

// By default
function foo(x, y) {
  let arr = [].concat(arguments);
  console.log(arr); //[Arguments(2)]
foo(1.2); / / set the Symbol. IsConcatSpreadable to true function foo(x, y) {  arguments[Symbol.isConcatSpreadable] = true;  let arr = [].concat(arguments);  console.log(arr); / / [1, 2] } foo(1.2); Copy the code

4.4, the Symbol. The iterator

Symbol. Iterator defines a default iterator for each object. This iterator can be used for… Of recycling.

const myIterable = {};
myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};  [...myIterable]; / / [1, 2, 3] Copy the code

Object for… In the of loop, the Symbol. Iterator method is called,

4.5, the Symbol. The match

Symbol. Match specifies that the match is a regular expression rather than a string. The string.prototype.match () method calls this function. In other words, if the property exists when str.match() executes, it returns the value of the method.

class foo {
  [Symbol.match](string) {
    return string;
"Jack".match(new foo()); // 'Jack' Copy the code

In addition to the above, MDN adds another feature to this attribute: this function is also used to identify whether an object has regular expression behavior. For example, the String. The prototype. The startsWith (), String. The prototype. The endsWith (“) and (String) prototype. Includes () these methods will check whether the first parameter is the regular expression. Raises a TypeError if it is a regular expression. Now, if the Match Symbol is set to false (or a false value), it means that the object is not intended to be used as a regular expression object.

"/bar/".startsWith(/bar/); // TypeError: First argument to String.prototype.startsWith must not be a regular expression
// When set to false
var re = /foo/;
re[Symbol.match] = false;
"/foo/".startsWith(re); // true
"/baz/".endsWith(re); // false Copy the code

4.6, Symbol. MatchAll

Symbol. MatchAll returns an iterator that generates regular expression matches based on the string. This function can be a String. The prototype. MatchAll () method call.

/ / equivalent to the
Copy the code

4.7, the Symbol. The replace

Replace this property specifies the method to be called when a string replaces the matched string. The string.prototype.replace () method calls this method.

String.prototype.replace(searchValue, replaceValue);
/ / is equivalent to
searchValue[Symbol.replace](this, replaceValue);
/ / case
class Replace1 {
 constructor(value) {  this.value = value;  }  [Symbol.replace](string) {  return `s/${string}/The ${this.value}/g`;  } }  console.log("foo".replace(new Replace1("bar"))); // "s/foo/bar/g" Copy the code

4.8, the Symbol. The search

Symbol. Search specifies a search method that takes the regular expression input from the user and returns the subscript that the regular expression matches in the String. This method is called by ().;
/ / equivalent to the
/ / case
class Search1 {
 [](str) {  return `${str} Word`;  } } "Hello".search(new Search1()); // Hello Word Copy the code

4.9, Symbol. Species

Symbol. Species is a function value attribute that is used by the constructor to create derived objects. In other words, the species accessor attribute allows subclasses to override the default constructor of the object.

Here’s an example:

// By default
class MyArray extends Array {}
let arr = new MyArray(1.2.3);
let brr = = > item);
brr instanceof MyArray; // true
brr instanceof Array; // true Copy the code

Class MyArray inherits from Array. Arr is an instance of MyArray, and BRR is a derivative of ARR. So BRR is an instance of MyArray, and BRR is also an instance of Array because of the archetype chain. If, at this point, we just want the BRR to be an instance of Array, the Symbol. Species attribute value comes in handy.

class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
let arr = new MyArray(1.2.3); let brr = = > item); brr instanceof MyArray; // false brr instanceof Array; // true // By default class MyArray extends Array {  static get [Symbol.species]() {  return this;  } } Copy the code

It is important to note that when you define the Symbol. Species attribute, you must declare it static and use the GET parser.

4.10, the Symbol. The split

Symbol. Split refers to the method of splitting a string at the index of a regular expression. This method is called via string.prototype.split ().

String.prototype.split(separator, limit);
/ / equivalent to the
separator[Symbol.split](this, limit);
/ / case
class Split1 {
 [Symbol.split](str) {  return `${str} Word`;  } } "Hello".split(new Split1()); // Hello Word Copy the code

4.11, Symbol. ToPrimitive

ToPrimitive is a built-in Symbol value that exists as a function value attribute of an object. This function is called when an object is converted to its original value. When called, this function passes a string argument hint that indicates the expected type of the original value to be converted to. There are three types of string hint: ‘number’, ‘string’, and ‘default’.

let obj =
    [Symbol.toPrimitive](hint) {
      switch (hint) {
        case "number":
 return 123;  case "string":  return "123";  case "default":  return "default";  default:  throw new Error(a); }  },  } + obj; / / 123 `${obj}`; / / '123' obj + ""; // "default" Copy the code

4.12, Symbol. ToStringTag

Symbol. ToStringTag is a built-in Symbol that is usually used as a key for an object’s property. The corresponding property value should be a string that represents the object’s custom type tag. Usually only built-in Object. The prototype. The toString () method to read the label and put it in his own return values. Popular point is the Object. The prototype. The toString () to judge, the data type of the custom Object returned is Object, can the label attribute to add custom Object type. Before I wrote “the road to relearn JS” JS foundation types and reference types wrote the most accurate judgment data type is the Object. The prototype. The toString (), as to why, but more elaborated in this, we can see this article.'123'); // [object String]
. moreCopy the code

Other object types are not, and the toString() method recognizes them because the engine sets a toStringTag tag for them: Map()); // "[object Map]"* () {}); // "[object GeneratorFunction]"; // "[object Promise]"
. moreCopy the code

Call when we define a class Object. The prototype. The toString (), because there is no internal definition toStringTag label, so can return “[Object Object]”

class Foo {} Foo()); // "[object Object]"
/ / set the Symbol. ToStringTag
class Foo {
  get [Symbol.toStringTag]() {
 return "Foo";  } } Foo()); // "[object Foo]" Copy the code

4.13, Symbol. Unscopabless

Symbol. Unscopables are the names of properties used to specify the value of an object, its object itself, and its inheritance that are excluded from the with environment binding of the associated object. In other words, attributes are the control of which attributes are removed by with in the with lexical environment.

/ / {
// copyWithin: true,
// entries: true,
// fill: true,
// find: true, // findIndex: true, // includes: true, // keys: true // } Copy the code

Here’s a brief introduction to the with function, which is used to value objects. Here’s a simple example:

let obj = {};
with (obj) {
  let newa = a;
  let newb = b;
  console.log(newa + newb);
} / / equivalent to the let newa = obj.a; let newb = obj.b; console.log(newa + newb); Copy the code

Advantages of with: When the values passed by with are very complex, that is, when objects are very complex nested structures, with makes the code look very concise. Disadvantages of with: The js compiler will check whether variables in the with block belong to the object passed by with. For example, js will check whether a and b belong to the obj object, which will greatly reduce the execution speed and performance of the with statement.

Back to the topic, let’s take an example of how the Symbol. Unscopables attribute works.

let obj = {
  foo() {
    return 1;
with(obj) {  foo(); / / 1 } // Set Symbol. Unscopables let obj = {  foo() {  return 1;  },  get [Symbol.unscopables]() {  return {  foo: true  }  } } with(obj) {  foo(); // Uncaught ReferenceError: foo is not defined } Copy the code

This is because with has removed the foo method from obj.

I also have a new understanding of Symbol this time. I hope it will be helpful to you. Like it! ๐Ÿ’ฅ ๐Ÿงก ๐Ÿ’–


Introduction to ECMAScript 6 — Symbol

After the language

  • Take you relearn ES6 | var, let and the difference between const
  • Take you relearn ES6 | Promsie
  • Take you relearn ES6 | Generator
  • Take you relearn ES6 | Async and Await
  • Take you relearn ES6 | Set and Map
  • Take you relearn ES6 | Symbol (more than just a new data type)
  • Take you relearn ES6 | Exprort (keep in mind that the output is variable)
  • Take you relearn ES6 | proxy and defineProperty

I think it’s ok, please give me a thumbs up when I leave, and we can study and discuss together!

You can also follow my blog and hope to give me a Start on Github, you will find a problem, almost all my user names are related to tomatoes, because I really like tomatoes โค๏ธ!!

The guy who wants to follow the car without getting lost also hopes to follow the public account or scan the qr code below ๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡.

I am a primary school student in the field of programming, your encouragement is the motivation for me to keep moving forward, ๐Ÿ˜„ hope to refueling together.

This article was typeset using MDNICE