Introduction to the

  • ES6: Refers to the ES2015 standard released in June 2015, but many people refer to ES2016, ES2017 and other standards when talking about ES6. Technically, it’s better to use a year. But it doesn’t matter. It doesn’t make much sense.
  • ESNext: A generic reference that always points to the next version. For example, if the current latest version is ES2020, then ESNext refers to the standard that will be released in June 2021.

Let and const

  • Variable promotion problem
console.log(i) // undefined
var i = 1;

console.log(letI) / / an error
let letI = 2;
Copy the code
  • Scope problem
for (var i = 0; i <= 3; i++) {
    setTimeout(function () {
        console.log(i); // 4 4 4 4
    }, 10);
}

// Other methods in ES5 implement printing correct results
for(var i = 0; i <=3; i++) {
    (function (i) {
        setTimeout(function () {
            console.log(i); // 0 1 2 3
        }, 10);
    })(i);
}
Copy the code

The reason:

  1. The variable defined by var is global, so there is only one variable I globally
  2. SetTimeout is asynchronous, the next round of the event loop, wait until it executes, to find a reference to the I variable. So the function finds the I after it’s gone through, and now it’s going to be 4
for(let i = 0; i <= 3; i++){ 
    setTimeout(function() {  
        console.log(i); // 0 1 2 3
    }, 10);
} 
Copy the code

The reason:

  1. Let introduces the concept of block-level scope, where the setTimeout function is created with the variable I in scope. For each iteration of the loop, the referenced I is a different instance of I.
  • Let defines variables, const defines constants (non-modifiable)

Arrow function

  • Short arrow function
const arrowFn = (value) = > Number(value);
/ / equivalent to
const arrowFn = function(value) {
    return value
}
// If you want to return a {}
const arrowFn = () = >({}); / / {})
const arrowFn = () = >{}; / / undefined x
/ / equivalent to
const arrowFn = () = > {
    return undefined
}
Copy the code
  • Arrow functions cannot be used as constructors
  1. What does the constructor do? Change this to refer to the object from the new instance
  2. What does the arrow function do? The this reference is determined at the time of the definition
  • The biggest difference: the arrow function “this” is defined while the normal function “this” is used
const teacher = {
    name: 'fj'.getName: function () {
        return `The ${this.name}`}}console.log(teacher.getName()); // fj

const teacher = {
    name: 'fj'.getName: () = > {
        return `The ${this.name}`}}console.log(teacher.getName()); // undefined because this points to window
// Note: Run undefined in JS and print null in HTML
Copy the code

class

class Test {
    _name = ' ';
    constructor(name) {
        this.name = name; // The set operation is performed at the same time as the instantiation
    }
    // Static properties: can only be called through class
    static getFormatName() {
        return `The ${this.name} - xixi`;
    }
    // Instance attributes: get, set (can only be called from a new instance)
    // Attribute names need to be consistent, so another variable can be used to store the real value
    get name() {
        return this._name;
    }

    set name(val) {
        console.log('name setter');
        this._name = val; }}console.log(new Test('fj').name); // name setter fj
console.log(Test.getFormatName()); // Test - xixi

/ / ES5
1.Instance attribute: test.prototype.xxx2.Static property: test.xxxCopy the code
  • Get and set: Data hijacking and encapsulating original data

Template string

const name = 'fj';
`${name}haha` ==  name + 'haha'

// Line feed is friendly
const huanh = `fj
fj
fj`
/ / equivalent to
const huanh = 'fj\nfj\nfj\n'; // Add an escape character
Copy the code

Implement simple render function

Title: Write render function, implement template render function

/ / known:
const year = '2021'; 
const month = '10'; 
const day = '01'; 
let template = '${year}-${month}-${day}';
let context = { year, month, day };

/ / implementation:
const str = render(template)(context); 
console.log(str) / / 2021-10-01
Copy the code

Higher-order functions: Running a function returns a new function render(template)(context)

function render(template) {
    return function(context){
        return template.replace(/ \ $\ {(. *?) \}/g.(match, key) = >context[key]); }}/ / resolution:
1.The key value obtained through regular matching is year month day2.Context is actually {year: '2021'.month: '10'.day: '01'}, so context['year'] = 2021..3.So context[key] is the resultCopy the code

deconstruction

  • Array deconstruction
// Base type destruct
let [a, b, c] = [1.2.3]
console.log(a, b, c) / / 1, 2, 3

// Object array destruct
let [a, b, c] = [{name: '1'}, {name: '2'}, {name: '3'}]
console.log(a, b, c) // {name: '1'}, {name: '2'}, {name: '3'}

/ /... deconstruction
let [head, ...tail] = [1.2.3.4]
console.log(head, tail) // 1, [2, 3, 4]

// Nested destruct
let [a, [b], d] = [1[2.3].4]
console.log(a, b, d) / / 1, 2, 4

// Destruct failed as undefined
let [a, b, c] = [1]
console.log(a, b, c) // 1, undefined, undefined

// Destruct the default assignment
let [a = 1, b = 2] = [3]
console.log(a, b) / / 3 and 2
Copy the code
  • Object structure
// Object attribute destruct
This is one of the differences between array deconstruction and object deconstruction
// Because the attribute names on the left and right sides of the object must be the same, otherwise an error will be reported
let { f2, f1 } = { f1: 'test1'.f2: 'test2' }
console.log(f1, f2) // test1, test2

// Deconstruct the object rename
let { f1: rename, f2 } = { f1: 'test1'.f2: 'test2' }
console.log(rename, f2) // test1, test2

// Nested destruct
let { f1: {f11}} = { f1: { f11: 'test11'.f12: 'test12'}}console.log(f11) // test11

/ / the default value
let { f1 = 'test1'.f2: rename = 'test2' } = { f1: 'current1'}
console.log(f1, rename) // current1, test2
Copy the code

Deconstruction theory

  • Of the iterableIteratorInterface, through the traverser in order to obtain the corresponding value for assignment
  • What is Iterator?
  1. Iterator is an interface that provides a unified access mechanism for various data structures. Any data structure that has an Iterator interface can be traversed. The for-of syntax in ES6 is equivalent to an Iterator, which automatically looks for the Iterator interface while iterating through data structures (for-of objects are not available).
  • What is Iterator for?
  1. Provides a unified access interface for various data structures
  2. Allows data structures to be processed in order
  3. You can iterate for of
  • How do I generate an iterable?
function generateIterator(array) {
    let nextIndex = 0
    return {
        // Return a next function with value and done in it
        next: () = > nextIndex < array.length ? {
            value: array[nextIndex++],
            done: false}, {value: undefined.done: true}}; }const iterator = generateIterator([0.1.2])
console.log(iterator.next())
Copy the code
  • What is an iterable?
  1. Is an implementation of the Iterator interface, just a protocol, and any object that follows that protocol can be an iterable.
  • An iterable must have two protocols:
  1. Iterable protocol: Objects must implement Iterator methods. That is, an object or its prototype chain must have oneSymbol.Iterator: () => Iterator protocol
  2. Iterator protocol: You must implement a next() method that returns an object with done(Boolean) and value attributes.
  • Implement for-of loop traversal
const obj = {
    count: 0[Symbol.iterator]: () = > {
        return {
            next: () = > {
                obj.count++;
                if (obj.count <= 10) {
                    return {
                        value: obj.count,
                        done: false}}else {
                    return {
                        value: undefined.done: true
                    }
                }
            }
        }
    }
}

for (const item of obj) {
    console.log(item)
}
Copy the code

traverse

  • for in
  1. When iterating through an array, key is the array subscript string
  2. Traversal object, key is the object field name.

Disadvantages:

  1. For in not only iterates through the current object, but also includes enumerable properties on the prototype chain ()
  2. For in is not suitable for traversing a number group and is mainly used as an object
  • for of

Advantages:

  1. Has the same concise syntax as for in, but without the drawbacks of for in
  2. Unlike the forEach method, it can be used with break, continue, and return
  3. Provides a unified operation interface for traversing all data structures

Object

Object.keys

This method returns an array of the given object’s own enumerable properties

const obj = { a: 1.b: 2 };
const keys = Object.keys(obj); // [a, b]
Copy the code

Object.values

This method returns an array of all enumerable property values for a given object itself

const obj = { a: 1.b: 2 };
const values = Object.values(obj); / / [1, 2]
Copy the code

Object.entries

This method returns an array of key-value pairs of the given object’s own enumerable properties.

const obj = { a: 1.b: 2 };
const keys = Object.entries(obj); // [ [ 'a', 1 ], [ 'b', 2 ] ]
Copy the code

Handwritten implementation functions simulate Object.keys, Object.values, object. entries?

function getObjectFun(obj) {
    const result = [];
    for (const prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            // Object.keys
            result.push(prop)
            // Object.values
            result.push(obj[prop]);
            // Object.entries
            result.push([prop,obj[prop]])
        }
    }

    return result;
}
console.log(getObjectFun{a: 1.b: 2})
Copy the code

Object.getOwnPropertyNames

This method returns an array of enumerable or non-enumerable property names that obJ owns.

Object.prototype.aa = '1111';

const testData = {
    a: 1.b: 2
}

for (const key in testData) {
    console.log(key); // a b aa
}

console.log(Object.getOwnPropertyNames(testData)); // [ 'a', 'b' ]
Copy the code

Object.getOwnPropertyDescriptor

What is a descriptor? For the corresponding property descriptor, is an object. Contains the following attributes:

  1. The configuration of different is configurable. Defaults to true to allow its properties to have properties (if false none of the following properties are valid)
  2. Writable Indicates whether it is writable. Default false, any overwriting of this property is invalid (an error will be reported in strict mode)
  3. Enumerable Whether erable is enumerable. Can be traversed in for-in or enumerated in object.keys

Object.defineProperty

Define a new property directly on an object, or modify an existing property of an object and return the object.

/ / writable
const object1 = {};
Object.defineProperty(object1, 'p1', {
  value: 'fj'.writable: true
});
object1.p1 = 'not fj';
console.log(object1.p1); // not fj, if writeable is false, fj
Copy the code

Data hijacking get set

const obj = {};
let val = undefined;
Object.defineProperty(obj,'name', {set: function(value) {
        console.log(`${value} - xxx`);
        val = value;
    },
    get: function() {
        return val;
    }
})
obj.name = 'fj';
console.log(obj.name)
// fj - xxx
// fj
Copy the code
const obj = new Proxy({}, {get: function(target,propKey) {
        console.log(`getting ${propKey}`)
        return target[propKey];
    },
    set: function(target,propKey,value) {
        console.log(`setting ${propKey} ${value}`);
        return Reflect.set(target,propKey,value);
    }
})
obj.name = 'fj';
console.log(obj.name);
// setting name fj
// getting name
// fj
Copy the code

Reflect

  1. Methods that include objects that are explicitly internal to the language (e.gObject.defineProperty) on the Reflect object.

    At this stage, some methods are deployed on both Object and Reflect objects, and future new methods will only be deployed on Reflect objects.

    That is, from the Reflect object you can get the methods inside the language
  2. Make all Object operations functions.

    Some Object operations are imperative, such asname in objdelete obj[name]And theReflect.has(obj, name)andReflect.deleteProperty(obj, name)It turns them into functional behavior.
  3. Reflect’s methods correspond to Proxy’s, and you can always get the default behavior at Reflect, no matter how the Proxy modifies it. This allows the Proxy object to easily call the corresponding Reflect method, completing the default behavior as a basis for modifying the behavior.

Summary: Reflect is a method introduced by the JS language in order to slowly optimize its previous non-normative behavior (if applicable or not)

Object.assign

A shallow copy. The latter attribute overrides the previous attribute when the same attribute is used

let obj = {name: 'fj'.age: 22.arr: [1.2]};
let newObj = Object.assign({},obj);
newObj.name = 'gx';
newObj.arr.push(3); // When referring to a type
console.log(obj) // { name: 'fj', age: 22, arr: [ 1, 2, 3 ] }
console.log(newObj) // { name: 'gx', age: 22, arr: [ 1, 2, 3 ] }
Copy the code

Handwritten shallow copy

function shallowClone(source) {
    const target = {};
    for(let i in source) {
        if(source.hasOwnProperty(i)) { target[i] = source[i]; }}return target;
}
let obj1 = {a:1.b:2.c: {c1: 3}};
let obj2 = shallowClone(obj1);
Copy the code

Object.is

Checks whether two values are the same value.

const a = {
    name: 1
};
const b = a;
console.log(Object.is(a, b)); // true
console.log(Object.is({}, {})); // false
Copy the code

Promise

Promise.all

function PromiseAll(promiseArray) {
    return new Promise(function (resolve, reject) {
        // Determine the parameter type
        if (!Array.isArray(promiseArray)) {
            return reject(new TypeError('arguments muse be an array'))}let counter = 0;
        let promiseNum = promiseArray.length;
        let resolvedArray = [];
        for (let i = 0; i < promiseNum; i++) {
            // 3. Here we use promise.resolve.
            Promise.resolve(promiseArray[i]).then((value) = > {
                counter++;
                resolvedArray[i] = value; // 2. Push instead of index assignment, ok
                if (counter == promiseNum) { ResolvedArr. Length === promiseNum
                    // 4. If you are not in the "then", you are in the "then".
                    resolve(resolvedArray)
                }
            }).catch(e= >reject(e)); }})}Copy the code

Promise.allSeettled

function PromiseAllSettled(promiseArray) {
    return new Promise(function (resolve, reject) {
        // Determine the parameter type
        if (!Array.isArray(promiseArray)) {
            return reject(new TypeError('arguments muse be an array'))}let counter = 0;
        const promiseNum = promiseArray.length;
        const resolvedArray = [];
        for (let i = 0; i < promiseNum; i++) {
            Promise.resolve(promiseArray[i])
                .then((value) = > {
                    resolvedArray[i] = {
                        status: 'fulfilled',
                        value
                    };

                })
                .catch(reason= > {
                    resolvedArray[i] = {
                        status: 'rejected',
                        reason
                    };
                })
                .finally(() = > {
                    counter++;
                    if (counter == promiseNum) {
                        resolve(resolvedArray)
                    }
                })
        }
    })
}
Copy the code

An array of

Array.flat (function flattening)

Returns recursively traversing the array at a specified depth and merging all elements with the elements in the traversed subarray into a new array

const arr1 = [1.2[3.4]];
arr1.flat();
// [1, 2, 3, 4]

const arr2 = [1.2[3.4[5.6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

const arr3 = [1.2[3.4[5.6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

// Use Infinity to expand nested arrays of any depth
const arr4 = [1.2[3.4[5.6[7.8[9.10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Copy the code

Handwriting function flattening

const arr1 = [1.2.3[1.2.3.4[2.3.4]]];
function flatDeep(arr, d = 1) {
    if (d > 0) {
        return arr.reduce((res, val) = > {
            if (Array.isArray(val)) {
                res = res.concat(flatDeep(val, d - 1))}else {
                res = res.concat(val);
            }
            returnres; }}, [])else {
        return arr.slice()
    }
};
console.log(flatDeep(arr1, Infinity))
Copy the code

Array.includes

Checks whether an array contains a specified value, returning true if it does, false otherwise.

const array1 = [1.2.3];
console.log(array1.includes(2)); // true
console.log(array1.includes(4)); // false
Copy the code

Array.from

Creates a new, shallow-copy array instance from an array-like or iterable

Array.from('foo'); // [ 'f', 'o', 'o' ]
Array.from([1.2.3].x= > x + x; // [2, 4, 6]
Array.from(new Set([1.2.3.3])); // [1, 2, 3]
Copy the code

How to convert Arguments to true array

  1. […arguments]
  2. Array.from(arguments)
  3. Array.prototype.slice.call(arguments)

How to weight

function unique (arr) {
  return Array.from(new Set(arr))
  // return [...new Set(arr)]
}
Copy the code
function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error! ')
        return
    }
    const array = [];
    for (let i = 0; i < arr.length; i++) {
        if(! array.includes(arr[i])) {//includes checks whether the array has a valuearray.push(arr[i]); }}return array
}
Copy the code