ECMAScript

An overview of the

ECMAScript, or ES, is the standard for JavaScript, which is the implementation of ECMAScript.

ECMAScript2015 is the representative version of ES. Compared with the last version, it has updated a lot of content. ES6 is the general name of the new standard after ES2015. The changes of ES6 compared with ES5.1 can be divided into four categories:

  • Fixed some problems and shortcomings in the original syntax, such as let and const keywords;

  • Enhancements to the original syntax, such as deconstruction, expansion, and parameter defaults;

  • New objects, methods, and functions, such as Promise, Proxy, etc.

  • New data types and data structures, such as Symbol, Map, etc.

Let and block-level scope

Scope: The accessible scope of variables and functions, that is, scopes control the visibility and life cycle of variables and functions.

Prior to ES6, there were only two types of scope: global scope and function scope.

With the release, the let and const keywords have been introduced, which define variables to form a block-level scope

// Global scope and function scope
var n = 1;  // defined in global scope
function fn() {
    var n = 1;  // The variable is defined in a function and can only be accessed in that function
}

//---------------------------------------------------------------------

// block-level scope
if (flag) {
    let n = 1  // defined in the if block
}

console.log(n)  // Printing variables outside of if that are internally defined will report the variable is not defined

Copy the code

When defining a variable, the var keyword promotes the variable, while let creates a temporary dead zone:

// var
console.log(a)
var a = 1
// This will not generate an error, just print a undefined

//---------------------------------------------------------------------
console.log(b)
let b = 1
B is not defined
Copy the code

Adding events to dom elements through loops prior to ES6 also caused some “unexpected” problems due to scoping:

var lis = document.getElementsByClassName('li')

for(var i = 0; i < lis.length; i ++) {
    lis[i].onClick =  function() {
        console.log(i)
    }
}
Copy the code

After successfully adding the click event to Li, no matter which LI is clicked, the printed value is always Lis.Length-1, which is different from our expected effect. This is also because after I is defined by var, I is defined globally. When the loop ends, the value of I has changed to lis.length-1, and when I click li again, it will print the same value. Before ES6, closures were used to solve this problem:

var lis = document.getElementsByClassName('li')

for(var i = 0; i < lis.length; i ++) {
    lis[i].onClick =  (function (count) {
            return function() {
            console.log(count)
    	}
    })(i) // This should be correct
}
Copy the code

After the let keyword, just defining the counter with let can solve such scoped problems:

let lis = document.getElementsByClassName('li')
for(let i = 0; i < lis.length; i ++) {
    lis[i].onClick =  function() {
        console.log(i)
    }
}
Copy the code

const

The const keyword is basically the same as let, except that const is defined as a constant and cannot be changed after it is defined:

const a = 4
a = 5
Copy the code

Assignment to constant variable Assignment to constant variable

Of course, by modifying the memory address of the member, it is ok to modify only the internal data of the reference data type:

const obj = {}
obj.name = 'I want to learn'
Copy the code

This is fine, but an error will still be reported if obj points to another memory address

const obj = {}
obj = []
// Uncaught TypeError: Assignment to constant variable
Copy the code

deconstruction

An array of deconstruction

Before ES6, when we wanted to extract an element from an array, we used an index to evaluate it

const arr = [0.1.2]
const n1 = arr[0]
const n2 = arr[1]
const n3 = arr[2]

// prints n1,n2,n3 as: 0, 1, 2
Copy the code

After the ES6 update, we can use array deconstruction to evaluate

const arr = [0.1.2]
const [n1, n2, n3] = arr

// prints n1,n2,n3 as: 0, 1, 2
Copy the code

And, of course, the following:

  1. If there are unwanted values, replace them with empty Spaces
const arr = [0.1.2]
const [ , , n1] = arr

// Prints n1 as: 2
Copy the code
  1. The array length is greater than the value length
const arr = [0.1.2]
const [ ,n1] = arr

// Prints n1 as: 1
Copy the code
  1. The array length is smaller than the value length
const arr = [0]
const [n1, n2] = arr

// Print n1,n2:0 undefined
Copy the code

Object to deconstruct

Unlike array deconstruction, which uses variables to match elements, object deconstruction is matched by attribute names. If no corresponding attribute name is matched, it becomes undefined. It is also possible to alias variables during deconstruction

const obj = {
    name: 'Study hard'.method: 'learning'
}
const { name, age, method: m } = obj

// name = 'study hard', age = 'undefined', m = 'study hard'
Copy the code

Template string

Before es6, strings were represented by double and single quotation marks, such as ‘string’ or “string”. If you want to wrap a string, use \n. If you want to add a variable in the middle of a string, you need to concatenate the string:

const name = 'Study hard'
const str = 'I want' + name + '了'

// Print STR as: 'I'm going to study hard'
Copy the code

If you encounter multiple strings and variable concatenation, it can be more messy, and es6 template strings greatly reduce such operations.

Template strings are enclosed in backquotes, which can be used as normal, but in cases like string concatenation, interpolation can be used to embed variables or even simple standard JS statements:

const name = 'Study hard'
const str = ` I want${name}The `

// Prints the result: 'I'm going to study hard'
Copy the code

Template string tag

Inside the template string, you can also add a tag function to it:

function tagFn(string) {
    return string
}
const name = 'cinit'
const toDo = 'Study hard'

const res = tagFnI `${name}to${toDo}The `
// res prints: [' I ', 'I ',' I ']
Copy the code

It can be seen that the tag function splits the template string according to the position of the variable. At the same time, it can also add the corresponding variable to the parameter of tagFn and get the corresponding value:

function tagFn(string, name, toDo) {
    return string[0] + name + string[1] + toDo + string[2]}const name = 'cinit'
const toDo = 'Study hard'

const res = tagFnI `${name}to${toDo}The `
// res prints: 'I cinit need to study hard'
Copy the code

Thus, we can manipulate variables in the template string within the tag function:

function tagFn(string, name, toDo) {
    name = name === 'cinit''我' : 'others'
    return string[0] + name + string[1] + toDo + string[2]}const name = 'cinit'
const toDo = 'Study hard'

const res = tagFnI `${name}to${toDo}The `
// res prints: 'I'm going to study hard'
Copy the code

String extension method

  • includes

    The includes method determines whether a string contains target characters

    const str = 'Study hard'
    console.log(str.includes('good'))
    // Prints: true
    Copy the code
  • startsWith

    StartsWith determines whether the string begins with the target character

    const str = 'Study hard'
    console.log(str.startsWith('good'))
    // Prints: true
    Copy the code
  • endsWith

    EndsWith determines whether the string endsWith the target character

    const str = 'Study hard'
    console.log(str.endsWith('learning'))
    // Prints: true
    Copy the code

Function defaults

For some functions, you can set default values to simplify function calls. Prior to ES6, it was mostly implemented this way:

function fn(name) {
    name = name === undefined ? 'cinit' : name
    console.log(name)
}
fn()
fn('wo')

// The function call prints:
// 'cinit'
// 'wo'
Copy the code

After ES6, the code can be simplified to:

function fn(name = 'cinit') {
    console.log(name)
}
fn()
fn('wo')

// The function call prints:
// 'cinit'
// 'wo'
Copy the code

Residual operator

Before ES6, you could call arguments inside a function for multiple arguments:

function fn() {
    console.log(arguments)
}
fn(1.2.2)
// Print the result: [1, 2, 2]
Copy the code

This argument is a pseudo-array

After ES6, we can use the remaining operators… To obtain the remaining parameters:

function fn(. args) {
    console.log(args)
}
fn(1.2.2)
// Print the result: [1, 2, 2]
Copy the code

After… Args forms an array to receive arguments passed to fn.

The array a

. Not only can it be used as a residual operator, it can also be used to expand an array

Before ES6, if you wanted to print every element in an array at the same time, you would normally pass in the array to print:

const arr = [1.2.3]
console.log.apply(console, arr)

// Prints the result: 1, 2, 3
Copy the code

After ES6, it can be simplified as:

const arr = [1.2.3]
console.log(... arr)// Prints the result: 1, 2, 3
Copy the code

. Each item of the array is passed to the function in turn

Arrow function

The arrow function in ES6 simplifies the way functions are defined to some extent. It contains the following features:

  • Use =, > and {} to describe a function

    const fn = (num1, num2) = > {
        num1 += 1
        num2 += 2
        return num1 + num2
    } 
    Copy the code
  • You must declare functions in the same way you define variables

    // wrong
    function(num1, num2) = >{
        num1 += 1
        num2 += 2
        return num1 + num2
    } 
    // right
    const fn = (num1, num2) = > {
        num1 += 1
        num2 += 2
        return num1 + num2
    } 
    Copy the code
  • When a function has one and only one parameter, you can omit the parentheses

    const fn = num= > {
        num += 1
        return num
    }
    Copy the code
  • When the function body has only one (return) statement, you can omit the braces

    const fn = num= > num + 1
    Copy the code
  • The this in the arrow function points to the this in the context in which it is defined

Object literals are enhanced

Before ES6, you might encounter the following when declaring variables as object literals

const name = 'Study hard'
const fn = function() {}
const obj = {
    // Attributes have the same key value names
    name: name,
    fn: fn,
}
// Add dynamic attribute names to the object
obj[Math.random()] = 1
Copy the code

After ES6, this can be changed to:

const name = 'Study hard'
const fn = function() {}
const obj = {
    // The key name of the property is the same
    name,
    fn,
    // Wrap variables in brackets when declaring them directly
    [Math.random()]: 1
}
Copy the code

Object extension method

Object.assign

The object.assign () method is used to assign the values of all enumerable properties from one or more source objects to target objects. It will return the target object.

Grammar:

Object.assign(target, ... sources)Copy the code

Parameters:

Target: indicates the target object.

Sources: source object.

The return value:

Target object.

const target = { a: 1.b: 2 };
const source = { b: 4.c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
{a: 1, b: 4, c: 5}

console.log(returnedTarget);
{a: 1, b: 4, c: 5}
Copy the code

If an attribute in the target object has the same key, the attribute is overwritten by an attribute in the source object. Properties of subsequent source objects similarly override properties of previous source objects.

The object. assign method copies only the enumerable properties of the source Object itself to the target Object. This method uses the source object’s [[Get]] and the target object’s [[Set]], so it calls the relevant getter and setter. Therefore, it assigns attributes, rather than just copying or defining new attributes. If the merge source contains getters, this may make it unsuitable to merge the new properties into the stereotype. To defined properties (including its enumerable) is copied to the prototype, the Object should be used. The getOwnPropertyDescriptor () and Object. The defineProperty ().

Both String and Symbol attributes are copied.

In the event of an error, for example, TypeError is raised if the property is not writable, and the target object can be changed if any properties are added before the error is raised.

Note that Object.assign will not throw an error if the source Object is null or undefined.

For deep copies, an alternative approach is needed because object.assign () copies (enumerable) property values.

If the source value is a reference to an object, it simply copies its reference value.

const log = console.log;

function test() {
  'use strict';
  let obj1 = { a: 0 , b: { c: 0}};
  let obj2 = Object.assign({}, obj1);
  log(JSON.stringify(obj2));
  // { a: 0, b: { c: 0}}

  obj1.a = 1;
  log(JSON.stringify(obj1));
  // { a: 1, b: { c: 0}}
  log(JSON.stringify(obj2));
  // { a: 0, b: { c: 0}}

  obj2.a = 2;
  log(JSON.stringify(obj1));
  // { a: 1, b: { c: 0}}
  log(JSON.stringify(obj2));
  // { a: 2, b: { c: 0}}

  obj2.b.c = 3;
  log(JSON.stringify(obj1));
  // { a: 1, b: { c: 3}}
  log(JSON.stringify(obj2));
  // { a: 2, b: { c: 3}}

  // Deep Clone
  obj1 = { a: 0 , b: { c: 0}};
  let obj3 = JSON.parse(JSON.stringify(obj1));
  obj1.a = 4;
  obj1.b.c = 4;
  log(JSON.stringify(obj3));
  // { a: 0, b: { c: 0}}
}

test();
Copy the code

Object.is

The object.is () method determines whether two values are the same.

Grammar:

Object.is(value1, value2);
Copy the code

Parameters:

Value1: the first value to be compared.

Value2: The second value to be compared.

The return value:

A Boolean type indicates whether two arguments have the same value.

Object.is('foo'.'foo');     // true
Object.is(window.window);   // true

Object.is('foo'.'bar');     // false
Object.is([], []);           // false

var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo);         // true
Object.is(foo, bar);         // false

Object.is(null.null);       // true

/ / special case
Object.is(0, -0);            // false
Object.is(0, +0);            // true
Object.is(-0, -0);           // true
Object.is(NaN.0/0);         // true
Copy the code

The object.is () method determines whether two values are the same. The two values are equal if the following conditions are met:

  • Are allundefined
  • Are allnull
  • Are alltruefalse
  • Are strings of the same length and the same characters are arranged in the same order
  • Are the same objects (meaning each object has the same reference)
  • It’s all numbers and
    • Are all+ 0
    • Are all0
    • Are allNaN
    • Or both are non-zero and notNaNAnd are the same value

It’s different from the == operation. The == operator casts the variables on both sides (if they are not of the same type) before determining equality (this behavior results in “” == false being true), while object. is does not cast the values on both sides.

It’s not the same as the === operation. The === operator (including the == operator) treats the numbers -0 and +0 as equal, and number.nan as unequal to NaN.

Proxy

Proxy objects are used to create a Proxy for an object to intercept and customize basic operations (such as property lookup, assignment, enumeration, function calls, and so on).

Terms:

  • Handler: A placeholder object that contains a trap and can be translated as a processor object.

  • Traps: Methods that provide access to properties. This is similar to the concept of a catcher in an operating system.

  • Target: indicates the object virtualized by Proxy. It is often used as the storage back end of an agent. Validate invariants (semantics that remain unchanged) about an object’s unextensibility or unconfigurable properties against the target.

Grammar:

const p = new Proxy(target, handler)
Copy the code

Parameters:

Target: The target object (which can be any type of object, including a native array, a function, or even another Proxy) to be wrapped with a Proxy.

Handler: An object that typically has functions as attributes that define the behavior of agent P when performing various operations.

Methods:

Proxy.revocable() : Creates an undoable Proxy object.

Methods of the handle:

The Handler object is a placeholder object that holds a set of specific properties. It contains the various traps of the Proxy.

All catchers are optional. If a catcher is not defined, the default behavior of the source object is retained.

  • handler.getPrototypeOf()

    Object. GetPrototypeOf method’s catcher.

  • handler.setPrototypeOf()

    The Object. SetPrototypeOf method’s catcher.

  • handler.isExtensible()

    Object. IsExtensible method of the catcher.

  • handler.preventExtensions()

    The catcher for the object. preventExtensions method.

  • handler.getOwnPropertyDescriptor()

    Object. GetOwnPropertyDescriptor trap method.

  • handler.defineProperty()

    A catcher for the object.defineProperty method.

  • handler.has()

    The catcher for the IN operator.

  • handler.get()

    The catcher for the property read operation.

  • handler.set()

    Property set the catcher for the operation.

  • handler.deleteProperty()

    The trap for the delete operator.

  • handler.ownKeys()

    Object, method and Object getOwnPropertyNames getOwnPropertySymbols trap method.

  • handler.apply()

    A catcher for a function call operation.

  • handler.construct()

    The catcher for the new operator.

Example:

// Basic example
const p = new Proxy({}, {
    get: function(obj, prop) {
        return prop in obj ? obj[prop] : 37;
    });
p.a = 1;
p.b = undefined;

console.log(p.a, p.b);      // 1, undefined
console.log('c' in p, p.c); // false, 37
Copy the code
// Validate the value passed to an object
let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid'); }}// The default behavior to store the value
    obj[prop] = value;

    // Indicates success
    return true; }};let person = new Proxy({}, validator);

person.age = 100;

console.log(person.age);
/ / 100

person.age = 'young';
// Throw an exception: Uncaught TypeError: The age is not an INTEGER

person.age = 300;
// Throw an exception: Uncaught RangeError: The age seems invalid
Copy the code

Reflect

Reflect is a built-in object that provides methods to intercept JavaScript operations. These methods are the same as the proxy Handlers method. Reflect is not a function object, so it is not constructible.

Reflect provides a whole set of methods for manipulating objects

Unlike most global objects, Reflect is not a constructor, so it cannot be called with the new operator or as a function. All attributes and methods of Reflect are static (just like Math objects).

The Reflect object provides the following static methods, which have the same name as Proxy Handler Methods.

Some of these methods are the same as Object, although there are some subtle differences.

Static method:

  • Reflect the apply (target, thisArgument argumentsList:

    Call a function and pass in an array as the call parameter. This is similar to function.prototype.apply ().

  • Reflect the construct (target, argumentsList [newTarget]) :

    New to the constructor is equivalent to executing a new target(… The args).

  • Reflect. DefineProperty (target, propertyKey, attributes) :

    Similar to Object.defineProperty(). Returns true on success

  • Reflect. DeleteProperty (target, propertyKey) :

    The delete operator of the function is equivalent to the delete target[name].

  • Reflect the get (target, propertyKey [, receiver]) :

    Gets the value of an attribute on the object, similar to target[name].

  • Reflect. GetOwnPropertyDescriptor (target, propertyKey) :

    Similar to the Object. GetOwnPropertyDescriptor (). Returns the property descriptor if the property exists in the object, otherwise undefined.

  • Reflect. GetPrototypeOf (target) :

    Similar to Object.getProtoTypeof ().

  • Reflect. From the (target, propertyKey) :

    Determining whether an object has a property is exactly the same as the in operator.

  • Reflect. IsExtensible (target) :

    Similar to the Object. IsExtensible ().

  • Reflect. OwnKeys (target) :

    Returns an array containing all of its own properties (excluding inherited properties). Keys () similar to Object.keys() but not affected by Enumerable.

  • Reflect. PreventExtensions (target) :

    Similar to object.preventExtensions (). Return a Boolean.

  • Reflect.set(target, propertyKey, value[, receiver]) :

    A function that assigns values to attributes. Returns a Boolean, true if the update succeeded.

  • Reflect. SetPrototypeOf (target, prototype) :

    A function that sets the object prototype. Returns a Boolean, true if the update succeeded.

Example:

// Checks whether an object has a specific attribute
const duck = {
  name: 'Maurice'.color: 'white'.greeting: function() {
    console.log(`Quaaaack! My name is The ${this.name}`); }}Reflect.has(duck, 'color');
// true
Reflect.has(duck, 'haircut');
// false
Copy the code
// Add a new attribute to an object
Reflect.set(duck, 'eyes'.'black');
// returns "true" if successful
// "duck" now contains the property "eyes: 'black'"
Copy the code

Promise

See the Promise of

Class

In object-oriented programming, a class defines the characteristics of an object. Classes are templates that define object properties and methods.

Prior to ES6, classes could be implemented through functions

function Student(name) {
    this.name = name
}

Student.prototype.greet = function () {
    console.log('hi')}Copy the code

When class is introduced in ES6, it can be changed to the following form:

class Student {
    constructor(name) {
        this.name = name
    }
    
    greet() {
        console.log('hi')}}Copy the code

Similar to Java, static methods and inheritance can also be implemented using static and extends:

class Student {
    constructor(name) {
        this.name = name
    }
    greet() {
        console.log('hi')}}class LiHua extends Student {
    constructor(name, major) {
        super(name)
        this.major = major
    }
    static study() {
        console.log('study English')}sayHi() {
        super.greet()
    }
}
Copy the code

Set

A Set object is a collection of values, and you can iterate over its elements in the order in which they were inserted. Elements in a Set occur only once, that is, the elements in a Set are unique.

The Set object allows you to store a unique value of any type, either a primitive value or an object reference.

NaN and undefined can both be stored in a Set, and NaN is treated as the same value.

The set data structure is itself a constructor.

Instance attributes:

  • size: Returns the number of values in the Set object

Instance methods:

  • Set. The prototype. The add (value) :

    Adds an element to the end of the Set. Returns the Set object.

  • Set. The prototype. The clear () :

    Removes all elements from Set.

  • Set. The prototype. The delete (value) :

    Returns set.prototype. has(value) the value that will be returned before this operation (that is, true if the element exists, false otherwise).

  • Set.prototype.has(value):

    False will be returned thereafter.

  • Set. The prototype. Entries () :

    Returns a new iterator object that contains the [value, value] array of the values of all elements in Set in insertion order. To keep the method similar to the Map object, the keys and values of each value are equal.

  • Set. The prototype. The forEach (callbackFn [, thisArg]) :

    CallBackFn is called once for each value in the Set, in insertion order. If thisArg argument is provided, this in the callback will be that argument.

  • Set. The prototype. From the (value) :

    Returns a Boolean value indicating whether the value exists in the Set.

  • Set. The prototype. The keys () :

    As with the **values()** method, returns a new iterator object containing the values of all elements in Set in insertion order.

  • Set. The prototype. The values () :

    Returns a new iterator object that contains the values of all elements in Set in insertion order.

/ / sample
let mySet = new Set(a); mySet.add(1); // Set [ 1 ]
mySet.add(5); // Set [ 1, 5 ]
mySet.add(5); // Set [ 1, 5 ]
mySet.add("some text"); // Set [ 1, 5, "some text" ]
let o = {a: 1.b: 2};
mySet.add(o);

mySet.add({a: 1.b: 2}); // o points to a different object, so no problem

mySet.has(1); // true
mySet.has(3); // false
mySet.has(5);              // true
mySet.has(Math.sqrt(25));  // true
mySet.has("Some Text".toLowerCase()); // true
mySet.has(o); // true

mySet.size; / / 5

mySet.delete(5);  // true to remove 5 from set
mySet.has(5);     // false, 5 has been removed

mySet.size; // 4, just removed a value

console.log(mySet);
// logs Set(4) [ 1, "some text", {…}, {…} ] in Firefox
// logs Set(4) {1, "some text", {... }, {... } } in Chrome
Copy the code
// Used for array de-duplication
const numbers = [2.3.4.4.2.3.3.4.4.5.5.6.6.7.5.32.3.4.5]
console.log([...new Set(numbers)])
// [2, 3, 4, 5, 6, 7, 32]
Copy the code

Map

The Map object holds key-value pairs and can remember the original insertion order of the keys. Any value (object or raw value) can be a key or a value.

Objects and Maps * * * *

Similarly, they all allow you to press a key to access a value, delete a key, and detect whether a key is bound to a value. So (and there’s no built-in alternative) we’ve always used objects as Maps. However, Maps and Objects have some important differences, and Map is a better choice in the following situations:

Map Object
The accident of key MapBy default, there are no keys. Contains only explicitly inserted keys. aObjectThere is a prototype, and the key name on the prototype chain may conflict with the key name you set on the object yourself. Although the ES5 works at firstObject.create(null)To create an object without a prototype, but this is not very common.
The type of the key aMapSigma could be PIAny value, including functions, objects, or any primitive type. aObjectTheta has to be a keyStringorSymbol.
The order of the keys MapKey is ordered in. So, when you iterate, oneMapObject returns key values in the order they are inserted. aObjectThe key is unordered note: objects since the ECMAScript 2015 specificationindeedPreserves the creation order of the string and Symbol key; Therefore, iterating over an object with only string keys produces keys in insertion order.
Size MapThe number of key-value pairs can be easily passedsizeProperties for ObjectThe number of key-value pairs can only be calculated manually
The iteration MapIterable, so it can be iterated directly. One iterationObjectYou need to get its keys somehow before you can iterate.
performance This is better when key pairs are frequently added or deleted. Optimizations are not made in cases where key/value pairs are frequently added and removed.

Create a Map object

const m = new Map(a)Copy the code

Map constructor attributes:

  • Map.length: The value of the length attribute is 0. I want to compute oneMapNumber of entries in, usingMap.prototype.size.

Map instance attributes:

  • The Map. The prototype. The constructor: return a function, it created the prototype of the instance. The default is the Map function.

  • Map.prototype.size: Returns the number of key/value pairs of the Map object.

Map instance method:

  • The Map. The prototype. The clear () :

    Removes all key/value pairs from the Map object.

  • The Map. The prototype. The delete (key) :

    If the element exists in the Map object, remove it and return true; Otherwise return false if the element does not exist. A subsequent call to map.prototype. has(key) returns false.

  • The Map. The prototype. Entries () :

    Returns a new Iterator containing the [key, value] array of each element in the Map, in insertion order.

  • Map. The prototype. The forEach (callbackFn [, thisArg]) :

    The callbackFn function is called once for each key-value pair in the Map, in insertion order. If thisArg is provided to forEach, it will be used as this in each callback.

  • The Map. The prototype. The get (key) :

    Returns the value of the key, or undefined if none exists.

  • The Map. The prototype. From the (key) :

    Returns a Boolean value indicating whether the Map instance contains the value corresponding to the key.

  • The Map. The prototype. The keys () :

    Returns a new Iterator containing the keys of each element in the Map in insertion order.

  • The Map. The prototype. The set (key, value) :

    Sets the value of the key in the Map object. Returns the Map object.

  • The Map. The prototype. The values () :

    Returns a new Iterator containing the values of each element in the Map in insertion order.

/ / sample
let myMap = new Map(a);let keyObj = {};
let keyFunc = function() {};
let keyString = 'a string';

/ / add the key
myMap.set(keyString, "Value associated with key 'a string'");
myMap.set(keyObj, "Value associated with keyObj");
myMap.set(keyFunc, "Value associated with keyFunc");

myMap.size; / / 3

/ / read the values
myMap.get(keyString);    // "Value associated with key 'a string'"
myMap.get(keyObj);       // "Value associated with keyObj"
myMap.get(keyFunc);      // "Value associated with keyFunc"

myMap.get('a string');   // "Value associated with key 'a string'"
                         // Because keyString === 'a string'
myMap.get({});           // undefined because keyObj! = = {}
myMap.get(function() {}); // undefined because keyFunc! == function () {}
Copy the code
/ / iteration
// for... of...
let myMap = new Map(a); myMap.set(0."zero");
myMap.set(1."one");
for (let [key, value] of myMap) {
  console.log(key + "=" + value);
}
// Two logs will be displayed. One is "0 = zero" and one is "1 = one"

for (let key of myMap.keys()) {
  console.log(key);
}
// Two logs will be displayed. One is zero and the other is one.

// forEach
myMap.forEach(function(value, key) {
  console.log(key + "=" + value);
})
// Two logs will be displayed. One is "0 = zero" and one is "1 = one"
Copy the code

Symbol

Symbol is a basic data type. The Symbol() function returns a value of type Symbol, which has static attributes and static methods. Its static attributes expose several built-in member objects; Its static method exposes the global Symbol registry, similar to the built-in object class.

Each Symbol value returned from Symbol() is unique. A symbol value can be used as an identifier for object properties; This is the only purpose of this data type.

/ / sample
const symbol1 = Symbol(a);const symbol2 = Symbol(42);
const symbol3 = Symbol('foo');

console.log(typeof symbol1);
// expected output: "symbol"

console.log(symbol2 === 42);
// expected output: false

console.log(symbol3.toString());
// expected output: "Symbol(foo)"

console.log(Symbol('foo') = = =Symbol('foo'));
// expected output: false


typeof Symbol() = = ='symbol'
typeof Symbol('foo') = = ='symbol'
typeof Symbol.iterator === 'symbol'
Copy the code

Symbol. The iterator:

A method that returns the default iterator of an object.

Symbol. HasInstance:

A method that determines whether an object recognized by a constructor object is an instance of it.

Symbol. IsConcatSpreadable:

A Boolean value that indicates whether an object should be flattened for its array elements.

Symbol. Unscopables:

The value of an object that owns and inherits attribute names is excluded from the related object bound to the environment.

Symbol. Species:

A constructor function that creates a derived object.

Symbol. ToPrimitive:

A method for converting an object to a primitive data type.

Symbol. ToStringTag:

String value for the default description of the object.

Methods:

Symbol. For (key) :

Search for an existing symbol with the given key and return it if found. Otherwise a new symbol is created in the global Symbol registry with the given key.

Symbol.prototype.toString()

Returns a string containing the Symbol descriptor. Cover the Object. The prototype. The toString () method.

Symbol.prototype.valueOf()

Returns the initial value of the Symbol object. Override the object.prototype.valueof () method.

Tips:

  • Symbols in the for… The in iteration is not enumerable. . In addition, the Object getOwnPropertyNames attributes of the Object (s) will not return to symbol, but can use the Object. The getOwnPropertySymbols () to get them.

  • When json.stringify () is used, properties with symbol values as keys are completely ignored.

for… of

for… The of statement creates an iteration loop over iterable objects (including Array, Map, Set, String, TypedArray, Arguments, HTMLCollection objects, and so on), calls custom iteration hooks, and executes statements for the values of each different property.

// Example iteration Array
const array1 = ['a'.'b'.'c'];

for (const element of array1) {
  console.log(element);
}

// expected output: "a"
// expected output: "b"
// expected output: "c"
Copy the code

Compare that to array forEach, for… “Of” can be terminated by break, throw continue, or return while iterating through an array. In these cases, the iterator closes.

Iterator interface

Iterative agreement

As a complement to ECMAScript 2015, the iteration protocol is not a new built-in implementation or syntax, but a protocol. These protocols can be implemented by any object that follows certain conventions.

Iteration protocol is divided into two protocols: iterable protocol and iterator protocol.

Iterable protocol

The iterable protocol allows JavaScript objects to define or customize their iterative behavior, for example, in a for.. In the of structure, which values can be traversed. Some built-in types are also built-in iterables and have the default iterative behavior, such as Array or Map, while others are not (such as Object).

To be an iterable, an object must implement the symbol. iterator method. This means that the object (or an object in its prototype chain) must have a property whose key is symbol. iterator. It is a no-argument function that returns an iterator protocol-compliant object.

When an object needs to be iterated over (such as by placing a for… First, its symbol. iterator method is called without arguments, and the iterator returned by this method is used to get the value to iterate over.

It is worth noting that when this zero-argument function is called, it is called as a method on the iterable. Therefore, inside a function, the this keyword can be used to access the properties of an iterable to determine what to provide during iteration.

This function can be a normal function or a generator function that returns an iterator object when called. Inside this generator function, yield can be used to supply each entry.

Iterator protocol

The iterator protocol defines a standard way to produce a series of values, whether finite or infinite. When a finite number of values are iterated over, a default return value is returned.

An object can be an iterator only if it implements a next() method with the following semantics:

attribute value
next A no-argument function that returns an object that should have the following two properties:doneBoolean if the iterator can produce the next value in the sequencefalse. (This is equivalent to not specifyingdoneThis property. If the iterator has iterated through the sequence, otherwisetrue. In this case,valueIs optional and, if it still exists, is the default return value at the end of the iteration.valueAny JavaScript value returned by the iterator. Done can be omitted when true.next()The method must return an object that should have two attributes:donevalueIf a non-object value is returned (e.gfalseundefined), will throw oneTypeErrorExceptions ("iterator.next() returned a non-object value").
// An iterator example
function makeIterator(array) {
    let nextIndex = 0;
    return {
       next: function () {
           return nextIndex < array.length ? {
               value: array[nextIndex++],
               done: false}, {done: true}; }}; }let it = makeIterator(['oh'.'ah']);

console.log(it.next().value); / / 'hey'
console.log(it.next().value); / / 'ah'
console.log(it.next().done);  // true
Copy the code

Here are the iterators in class:

class SimpleClass {
  constructor(data) {
    this.data = data
  }

  [Symbol.iterator]() {
    // Use a new index for each iterator. This makes multiple
    // iterations over the iterable safe for non-trivial cases,
    // such as use of break or nested looping over the same iterable.
    let index = 0;

    return {
      next: () = > {
        if (index < this.data.length) {
          return {value: this.data[index++], done: false}}else {
          return {done: true}
        }
      }
    }
  }
}

const simple = new SimpleClass([1.2.3.4.5])

for (const val of simple) {
  console.log(val)   //'1' 2' 3' 4' 5'
}
Copy the code

Generator

The generator object is returned by a generator function and conforms to both the iterable and iterator protocols.

/ / sample
function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

let g = gen();
// "Generator { }"
Copy the code

Tips

A generator object is both an iterator and an iterable because it conforms to both the iterable and iterator protocols:

let aGeneratorObject = function* (){
    yield 1;
    yield 2;
    yield 3; } ();typeof aGeneratorObject.next;
// return "function", which is an iterator because there is a next method

typeof aGeneratorObject[Symbol.iterator];
// Return "function", which is an iterable because there is a symbol. iterator method

aGeneratorObject[Symbol.iterator]() === aGeneratorObject;
// Returns true, because the symbol. iterator method returns itself (that is, the iterator), so this is a well-formed iterable

[...aGeneratorObject];
// Return [1, 2, 3]

console.log(Symbol.iterator in aGeneratorObject)
// Returns true because the symbol. iterator method is an attribute of the aGeneratorObject
Copy the code

We can also use for… Of to iterate over the generator object:

function* fibonacci() { // a generator function
    let [prev, curr] = [0.1];
    for (;;) { // while (true) {
        [prev, curr] = [curr, prev + curr];
        yieldcurr; }}for (let n of fibonacci()) {
     console.log(n);
    // Break out of the loop when n is greater than 1000
    if (n >= 1000)
        break;
}
Copy the code

ES2016

Compared to ES2015, ES2016 has only minor updates, such as the includes method for arrays and the index operator **.

Array.prototype.includes

The includes method is used to determine whether an array contains a specified value, returning true if it does and false otherwise.

/ / sample
const array1 = [1.2.3];

console.log(array1.includes(2));
// expected output: true

const pets = ['cat'.'dog'.'bat'];

console.log(pets.includes('cat'));
// expected output: true

console.log(pets.includes('at'));
// expected output: false
Copy the code

In contrast to array.prototype. indexOf, includes queries NaN in an Array, meaning that includes can determine if an Array contains NaN.

[1.2.NaN].includes(NaN); // true
Copy the code

Includes can also be passed a second parameter, fromIndex, which will use formIndex as the index to start the search and later target values:

// If fromIndex is greater than or equal to the length of the array, false is returned and the array is not searched.
[1.2.3].includes(3.3);  // false

// If fromIndex is negative, the calculated index will be the place to start the searchElement search. If the calculated index is less than 0, the entire array is searched.
[1.2.3].includes(3, -1); // true
Copy the code

Exponential operator

Like the +, -, *, / operators, exponentiation has a special operator: **. The exponential operator is much simpler than math.pow () :

2六四屠杀10  / / 1024
Copy the code

ES2017

Object.values

The object. values method returns an array of all the enumerable property values of a given Object itself.

/ / sample
const obj = { foo: 'bar'.baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]
Copy the code

Object.entries

The object. entries method returns an array of key-value pairs for the given Object’s own enumerable properties.

/ / sample
const obj = { foo: 'bar'.baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
Copy the code

Thus, you can use for… in this way. Of iterates over an object:

const object1 = {
  a: 'somestring'.b: 42
};

for (const [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

// "a: somestring"
// "b: 42"
Copy the code

We can also convert Object to a Map Object:

const obj = { foo: "bar".baz: 42 };
const map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }
Copy the code

String.prototype.padStart/Sting.prototype.padEnd

The padStart/padEnd method populates the current string with another string so that the resulting string is of a given length. PadStart starts filling from the left and padEnd starts filling from the right.

const str1 = '5';

console.log(str1.padStart(2.'0')); / / "05"
console.log(str1.padEnd(2.'0')); / / "50"
Copy the code