Study notes - ES2015--22-03-05 (Symbol,for...of...,Iterator,generator,getter setter,ES2016,ES2017)

Posted by Meissa on Sat, 05 Mar 2022 10:54:29 +0100


Symbol is a new basic type; The main function is to define unique attribute names. This feature can also be used to protect private variables. Because the outside world cannot generate the same symbol, it cannot be accessed;

If you want to reuse this symbol, you can use the static method symbol for(value: string); The Global Registry will record the correspondence between this string and symbol, so if the incoming value is not a string, it will be converted into a string;

Symbol property cannot be used by for In and object Keys () and so on. Similarly, the symbol attribute value will be ignored during json serialization; But you can use object Getownpropertysymbols() get

obj = {name: 'zs', age:22, [Symbol()]:2};
console.log(Reflect.has(obj, 'name')); // true
console.log(Reflect.deleteProperty(obj, 'name')); // true
console.log(Reflect.ownKeys(obj)); // [ 'age', Symbol() ]
console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol() ]


for # of # is a unified way to traverse all data structures # requires data to implement an iterative interface # iterable interface

For # of # can use break to terminate the loop # for # of can traverse all iteratable objects # or even pseudo array # Set # Map

Traversing the map obtains an array. Array 0 is the key and 1 is the value of # for (const [key, value] of # map)

arr.forEach() / / the loop cannot be terminated

        arr.some(); return true: terminate

        arr.every(); return: false: terminate

const arr = [1,2,3,4,2,2,44];

for (const item of arr) {
    if (item >= 4) break;
// You can jump out of the loop through break

Why does const be used to define for of while const is used to report an error?

Because for # in # and for # of # will create a separate block level scope for each cycle, const is used to ensure that the value will not be modified, while ordinary for will only create a block level scope;


The Iterable interface needs to be implemented when using for of to traverse the data structure

By printing iteratable data structures such as array _ set map, it is found that they are in the proto type object (__) Both:

Symbol(Symbol.iterator): ƒ values()
        arguments: (...)
        caller: (...)
        length: 0
        name: "values"
        __proto__: ƒ ()
        [[Scopes]]: Scopes[0]

When you call this method, you can see a next method:

Array Iterator {}
  __proto__: Array Iterator
    next: ƒ next()
        arguments: (...)
        caller: (...)
        length: 0
        name: "next"
        __proto__: ƒ ()
        [[Scopes]]: Scopes[0]
    Symbol(Symbol.toStringTag): "Array Iterator"
    __proto__: Object

View, obtain and execute next through the set structure:

const set = new Set();
const iterator = set[Symbol.iterator]();
console.log(; // { value: '22', done: false }
console.log(; // { value: '33', done: false }
console.log(; // { value: 'wa', done: false }
console.log(; // { value: undefined, done: true }
console.log(; // { value: undefined, done: true }

Simulate this iterator manually:

const obj = {
    arr: ['qqq','www','eee'],
    [Symbol.iterator]: function() {
        let index = 0;
        const self = this;
         *  {arr: [ 'qqq', 'www', 'eee' ],
                [Symbol(Symbol.iterator)]: [Function: [Symbol.iterator]]}
        return {
            next() {
                const result = {
                    value: self.arr[index],
                    done: index >= self.arr.length,
                index ++;
                return result;

for (const item of obj) {
    // qqq
    // www
    // eee

4.generator generator

ES2015 appears mainly to solve the problem of asynchronous nesting; But there are disadvantages: it is necessary to define an additional executor method and call methods such as next () to execute the generator object;

function * a() {
    let index = 0;
    console.log(index); // 0
    const obj1 =  yield index++;
    console.log(obj1); // undefined
    const obj2 =  yield index++;
    console.log(obj2); // 1
    const obj3 =  yield index++;
    const obj4 =  yield index++;
    return 'return 1';

const g = a();
console.log(g); // Object [Generator] {}

let value =; 
console.log(value,333); // { value: 0, done: false }
value =; 
console.log(value,334); // { value: 1, done: false }
value =;
console.log(value); // { value: 2, done: false }

Using the generator, you can define iteratable attributes more easily:

// Iterators can be implemented through generators
const obj = {
    arr: ['qqq','www','eee'],
    [Symbol.iterator]: function * () { 
        const all = [...this.arr,]
        for (const item of all) { // for of is used here because the array implements the iterator by default. You can also use other methods to iterate
            yield item;
for (const item of obj) {
    // qqq
    // www
    // eee
// Return the iterator to a generator function. When accessed externally through for of, for of will call the next method of the iterator, so that the object can be iterated

5.getter setter

         getter ES2015 get property () {return ...} No parameters allowed

        set prop(val) { . . . } one parameter

After ES2015, you can use get [express] () {} to define getter s and setter s for calculating property names

The created attribute is a pseudo attribute, and its assignment will not affect it

You can delete using delete

You can use defineProperty to define an existing object;

The delay calculation can only be calculated when necessary. When defining, the performance can be optimized with the help of cache;

When the get keyword is used, it is similar to object Defineproperty () has a similar effect, with slight differences when used in classes.

When using the get keyword, the attribute will be defined on the prototype of the instance. When using object When defineproperty(), the property will be defined on the instance itself.

        Object. The values of object.03 and 22.04 assign cannot be copied

If you want to copy getter s and setter s, you can use getOwnPropertyDescriptor to get the descriptor information of the specified property, and then add the descriptor through defineProperty

class Example {
    get hello() {
        return 'world';
const obj3 = new Example();
// "world"

console.log(Object.getOwnPropertyDescriptor(obj3, 'hello'));
// undefined

    Object.getPrototypeOf(obj3), 'hello'
// { configurable: true, enumerable: false, get: function get hello() { return 'world'; }, set: undefined }

6. New features of es2016

arr.includes() determines whether the array has the specified value, and returns boolean() to determine whether the two NaN are equal

arr.indexOf() returns that if the index cannot be found, it returns - 1 to judge that the two NaN are not equal

Exponential operator * * 2 * * 10 = = = 1024

7. New features of es2017

        Object.values(obj) returns the Array of all values of the object

        Object.entries(obj) returns the Array of all key value pairs of the object. The key value is also Array

You can use entries with for of to implement traversal instead of implementing the iterable interface

for (const [key, value] of Object.entries(obj)) {
    console.log(key, value);

        Object. The getownpropertydescriptors () method is used to obtain the descriptors of all its own properties of an object

        Object.getOwnPropertyDescriptor(obj1,'all') method returns the descriptor of the property of the object;

Async / wait , is simpler than the generator, and the synchronous writing method is easier to read , which is actually a Promise syntax sugar; A common value in return is that , will wrap it as Promise , similar to Promise Resolve() static method; (Promise source code learning notes needtodo)

Topics: Javascript ECMAScript