10 minutes to understand the important features of ES6+(ES2015-ES2019)

ES2015(ES6)

ES2015 is the sixth version of ECMA Script(JS) released in 2015, so it is also called ES6. Since then, ECMA Script has released a large version every year and added some important features, which we call ES6 +.

This paper mainly summarizes the main features of ES2015-ES2019. A learning front-end children's shoe should be some commonly used and understood features.

Main functions of ES2015:

  • Solve some shortcomings of the original grammar
  • Enhance the original syntax
  • New objects, new methods, new functions

Promise,Proxy,Object.assign, etc

  • New data types and data structures

Symbol, Set, Map, etc

Environmental support commonly used in ES2015

  • nodejs query: https://node.green/
  • Browser query: http://kangax.github.io/compat-table/es6/

PC browser support for ES2015

  • Chrome: 97% of the new features of ES6 can be supported from version 51.
  • Firefox: 97% of the new ES6 features can be supported from version 53.
  • Safari: 99% of the new features of ES6 can be supported from version 10.
  • Edge: Edge 15 can support 96% of the new ES6 features. Edge 14 can support 93% of the new features of ES6.
  • Ie: IE7 ~ 11 basically does not support ES6

Support of mobile browser for ES2015

  • iOS: 99% of the new features of ES6 can be supported from version 10.0.
  • Android: basically does not support the new features of ES6 (5.1 only supports 25%)

The server's support for ES2015 is as follows: https://node.green/

  • Node.js: 97% of the new features of ES6 can be supported from version 6.5. (6.0 support 92%)

var (compare let and const)

  • There are only global scope and function scope, and there is no strict block level scope
  • Variable promotion exists
  • Variables can be declared and defined separately
  • Variables can be declared repeatedly

let (block level scope)

  • Block level scope exists
  • Cannot promote variable
  • Variables can be declared and defined separately
  • Variable cannot be declared repeatedly

const constant

  • Block level scope exists
  • Cannot promote variable
  • The declaration and definition of variables must be in the same statement
  • Variable cannot be declared repeatedly
  • The declared variable value cannot be modified (for example, the attribute value of the object can be modified, but the object address cannot be modified)
  • Best practice: use const instead of var and let instead

Array deconstruction

const [foo, bar, baz] = arr
console.log(foo, bar, baz)

const [, , baz] = arr
console.log(baz)

// Deconstruct the remaining array elements
// The extension operator can only be used at the last position
const [foo, ...rest] = arr
console.log(rest)

// There are few elements during deconstruction, and the elements are taken in order
const [foo] = arr
console.log(foo)

// Set default values during deconstruction
const [foo, bar, baz = 123, more = 'default value'] = arr
console.log(bar, more)

Object deconstruction

const obj = { name: 'zce', age: 18 }

// When the variable name is repeated, you can rename and set the default value
const name = 'tom'
const { name: objName = 'jack' } = obj
console.log(objName)

Template string

  • Line breaks are supported
  • Support embedded variables and expressions
const name = 'tom'
// You can insert an expression through ${}, and the execution result of the expression will be output to the corresponding position
const msg = `hey, ${name} --- ${1 + 2} ---- ${Math.random()}`
console.log(msg)

String extension method

  • includes contains a string
  • Does startsWith start with a string
  • Does endsWith end with a string
const message = 'Error: foo is not defined.'

console.log(
  // message.startsWith('Error')
  // message.endsWith('.')
  message.includes('foo')
)

Method's parameter defaults

  • Use = after the function parameter to set the default value
  • The default value will be set only when the formal parameter is passed as undefined or no value is passed (false will not be used)
  • If there are only some default values, you need to put the code for setting the default value later; Otherwise, it cannot be used normally
// The default parameter must be at the end of the formal parameter list
function foo (bar,enable = true) {
  console.log('foo invoked - enable: ')
  console.log(enable)
}

foo(false)

Remaining parameters of method

  • It can only appear in the last bit of the formal parameter
  • It can only be used once
  • args is an array, which is different from that arguments is a pseudo array
function foo (first, ...args) {
  console.log(args)
}

foo(1, 2, 3, 4)

Expand array

const arr = ['foo', 'bar', 'baz']

// console.log(
//   arr[0],
//   arr[1],
//   arr[2],
// )

// console.log.apply(console, arr)

console.log(...arr)

Arrow function

Plug in: Fira Code font makes arrows look better

const arr = [1, 2, 3, 4, 5, 6, 7]

// arr.filter(function (item) {
//   return item % 2
// })

// Common scenarios, callback functions
arr.filter(i => i % 2)

Abbreviation for arrow function

function(value){return value} Equivalent to value=>value

this point of the arrow function

  • this of a normal function points to the object that calls its method
  • The direction of this of the arrow function is the same as that of the function outside it, that is, the arrow function will not change the direction of this
// Arrow function and this
// The arrow function does not change the direction of this

const person = {
  name: 'tom',
  // sayHi: function () {
  //   console.log(`hi, my name is ${this.name}`)//tom, this points to the caller of the function
  // }
  sayHi: () => {
    console.log(`hi, my name is ${this.name}`) //undefined, this is the same as the function this outside sayHi()
  },
  sayHiAsync: function () {
    // const _this = this
    // setTimeout(function () {
    //   console.log(_this.name) / / this here is window, so you need to use_ this
    // }, 1000)

    console.log(this)
    setTimeout(() => {
      // console.log(this.name) / / this here points to this in sayHiAsync, that is, person
      console.log(this)
    }, 1000)
  }
}
person.sayHi()
person.sayHiAsync()

Object Literal

  • If the attribute name is the same as the variable name of the value, you can omit a variable
  • Abbreviation of method: you can omit ": function"
  • Calculate attribute name: any expression can be used for attribute name in []
const bar = '345'

const obj = {
  foo: 123,
  // bar: bar
  // The attribute name is the same as the variable name, and can be omitted: bar
  bar,
  // method1: function () {
  //   console.log('method111')
  // }
  // Method can be omitted: function
  method1 () {
    console.log('method111')
    // this method is an ordinary function. this points to obj.
    console.log(this)
  },
  // Math.random(): 123 / / not allowed, use []
  // Use [] to make the result of the expression as the property name
  [bar]: 123
}

Object.assign

Object. Is assign an incomplete deep copy? How much did it copy?
Unable to get the get and set information in obj

  • Assign values from the source object to the target object
  • The target object and the return value are the same object
  • If there is a property with the same name in the target object, the property is overwritten
  • You can pass in multiple source objects and overwrite the target objects in order
const source1 = {
  a: 123,
  b: 123
}

const source2 = {
  b: 789,
  d: 789
}

const target = {
  a: 456,
  c: 456
}

const result = Object.assign(target, source1, source2)

console.log(target)
console.log(result === target) //true, the target object and return value are one object

Object.is

0 == false              // => true
0 === false             // => false
+0 === -0               // => true
NaN === NaN             // => false
Object.is(+0, -0)       // => false
Object.is(NaN, NaN)     // => true

Proxy and object defineProperty

Role of Proxy
Listen for Object attribute changes

Compare object defineProperty
Reference notes: https://gitee.com/ymcdhr/e-task/wikis/?sort_id=4053906

Reflect (unified method of operating Object)

  • The method in Reflect is called by default in the method of Proxy attribute, for example:
const obj = {
  foo: '123',
  bar: '456'
}

const proxy = new Proxy(obj, {
  get (target, property) {
    console.log('watch logic~')
    // This method is called by default if it is not written in the Proxy
    return Reflect.get(target, property)
  }
})
  • Relect provides a unified method for operating Object objects. There are 13 complete methods on MDN:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

// console.log('name' in obj)
// console.log(delete obj['age'])
// console.log(Object.keys(obj))

console.log(Reflect.has(obj, 'name'))
console.log(Reflect.deleteProperty(obj, 'age'))
console.log(Reflect.ownKeys(obj))

Promise

Reference documents: js single thread mechanism and asynchronous programming (Promise, Generator, Async, Await)

Basic syntax of Class

// class keyword

// function Person (name) {
//   this.name = name
// }

// Person.prototype.say = function () {
//   console.log(`hi, my name is ${this.name}`)
// }

class Person {
  // Constructor
  constructor (name) {
    this.name = name
  }
  // Member variable
  age = 18
  // Member function
  say () {
    console.log(`hi, my name is ${this.name}`)
  }
}

const p = new Person('tom')
p.say()

static method in Class

  • Declaring static methods: static keyword
  • Call static method: person say
  • this of static method points to class
// static method

class Person {
  constructor (name) {
    this.name = name
  }

  say () {
    console.log(`hi, my name is ${this.name}`)
  }

  static create (name) {
    return new Person(name)
  }
}

const tom = Person.create('tom')
tom.say()

Class inheritance

  • Use extensions inheritance
  • Pay attention to the use of super and be able to access the parent class; It is usually used to execute the constructor of the parent class.
class Person {
  constructor (name) {
    this.name = name
  }

  say () {
    console.log(`hi, my name is ${this.name}`)
  }
}

class Student extends Person {
  constructor (name, number) {
    super(name) // Call the parent constructor, otherwise name has no assignment (important)
    this.number = number
  }

  hello () {
    super.say() // Call parent class member
    console.log(`my school number is ${this.number}`)
  }
}

const s = new Student('jack', '100')
s.hello()

Set,Map

Set an array collection without duplicate elements

Common member methods

  • s.add(item) adds an item and returns the collection itself, which can be called in a chain
  • s.size gets the length of the Set
  • s.has(item) determines whether an item exists
  • s.delete(item) deletes an item
  • s.clear() delete all
const s = new Set()
s.add(1).add(2).add(3).add(4).add(2)
// console.log(s)

// s.forEach(i => console.log(i))  //forEach,for...of can be used to traverse Set

// for (let i of s) {
//   console.log(i)
// }

// console.log(s.size)
// console.log(s.has(100))
// console.log(s.delete(3))
// console.log(s)
// s.clear()
// console.log(s)

Commonly used for array de duplication

// Application scenario: array de duplication
const arr = [1, 2, 1, 3, 4, 1]

const result1 = Array.from(new Set(arr))
const result2 = [...new Set(arr)]

console.log(result1,result2)

Map is a collection of objects that can use complex structures as attributes

When storing object properties in previous objects, complex data will be converted into strings (toString() method), as follows:

const obj = {}
obj[true] = 'value'
obj[123] = 'value'
obj[{ a: 1 }] = 'value'

console.log(Object.keys(obj))

//0: "123"
//1: "true"
//2: "[object Object]"

Using Map, you can store complex data as object attributes. Common methods are as follows:

const m = new Map()
const tom = { name: 'tom' }
m.set(tom, 90)
console.log(m)
console.log(m.get(tom))

// m.has()
// m.delete()
// m.clear()

// forEach can traverse the item s in the Map
m.forEach((value, key) => {
  console.log(value, key)
})

Symbol

A brand-new basic data type. Each creation is a unique value

let s = Symbol();

typeof s
// "symbol"

let s1 = Symbol('foo');
let s2 = Symbol('foo');

s1 === s2 // false

// The for method creates the same value, and the parameters are automatically converted to strings
let s3 = Symbol.for('foo');
let s4 = Symbol.for('foo');

s3 === s4 // true

It can be converted into a string through description (method provided by ES2019)

let s1 = Symbol('foo');
let s2 = Symbol('foo');

s1 // Symbol(foo)
s2 // Symbol(foo)

s1 === s2 // false

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(foo)"
s1.description // "Foo" / / method provided by es2019

It can be used as the property name of the object to avoid the conflict of the same name

const obj = {}
obj[Symbol()] = '123'
obj[Symbol()] = '456'
console.log(obj)
//Symbol(): "123"
//Symbol(): "456"

When defining an attribute with a Symbol value, the Symbol value must be placed in square brackets and the dot operator cannot be used

let s = Symbol();

// The first way to write
let a = {};
a[s] = 'Hello!';

// The second way to write
let a = {
  [s]: 'Hello!'
};

// The same result is obtained in the above writing
a[s] // "Hello!"

It can be used as a private member of an object. It cannot be accessed directly from the outside (because each access is different). It can only be accessed through the internal this

// Case 2: Symbol simulates the implementation of private members

// a.js ======================================

const name = Symbol()
const person = {
  [name]: 'zce',
  say () {
    console.log(this[name])
  }
}
// Only expose person

// b.js =======================================

// Since the same Symbol value cannot be created,
// Therefore, you cannot directly access the "private" members in person
// person[Symbol()]
person.say()

Note: for... in, object keys,Json.stringify cannot be used on symbols
Use: object Getownpropertysymbols instead of obeject The keys method is used for symbols

for... of unified traversal method

The previous for... in traverses key value pairs, and forEach has limitations

  1. You can use break to terminate the traversal, and forEach cannot jump out of the loop
  2. You can traverse Array, Set, and Map objects
  3. An ordinary object cannot be traversed directly by for... of because it has no symbol Iterator property
  • The reason why an Object does not deploy the Iterator interface by default is that it is uncertain which attribute of the Object is traversed first and which attribute is traversed later, which needs to be manually specified by the developer.
  1. All objects that can use for... of need to have symbol Iterator property
// for...of cycle
const arr = [100, 200, 300, 400]

// for... The of loop can replace the forEach method of an array object, but you can use break to jump out of the loop
arr.forEach(item => {
  console.log(item)
})

for (const item of arr) {
  console.log(item)
  if (item > 100) {
    break
  }
}

// forEach cannot jump out of the loop. You must use some or every methods
// arr.forEach() / / cannot jump out of the loop
// arr.some()
// arr.every()

// Traversing a Set is the same as traversing an array
const s = new Set(['foo', 'bar'])

for (const item of s) {
  console.log(item)
}

// Traversing the Map can cooperate with the array structure syntax to directly obtain the key value
const m = new Map()
m.set('foo', '123')
m.set('bar', '345')

for (const [key, value] of m) {
  console.log(key, value)
}

// Ordinary objects cannot be used directly for Of traversal
const obj = { foo: 123, bar: 456 }

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

Iteratable interface iterator (mainly used for... of)

  • Prototype objects of some data structures_ proto _ Contains symbol Iterator method
  • The iterator method returns a pointer object with the next() method
  • Each time the next() method is executed, it returns the next data

With symbol Data structure of iterator property

Array, Map, Set, String, TypedArray, arguments object of function, NodeList object

The iterator traversal process is like this.

  • (1) Create a pointer object to the starting position of the current data structure. That is, the traverser object is essentially a pointer object.
  • (2) By calling the next method of the pointer object for the first time, you can point the pointer to the first member of the data structure.
  • (3) The second time the next method of the pointer object is called, the pointer points to the second member of the data structure.
  • (4) Keep calling the next method of the pointer object until it points to the end of the data structure.

Enables objects to use for... of

const obj = {
  // Use calculation attribute and save expression attribute name with []
  // 1. Iterable, the object must have a symbol Iterator property
  [Symbol.iterator]: function () {
    return {
      // 2. Iterator, the returned object has a next() method
      next: function () {
        // 3. The IterationResult, next() method returns an object
        return {
          value: 'zce',
          done: true
        }
      }
    }
  }
}

for (const item of obj) {
  console.log('Circulatory body', item)
}

Enable objects to use for... of, complete code

const obj = {
  store: ['foo', 'bar', 'baz'],

  [Symbol.iterator]: function () {
    let index = 0
    const self = this

    return {
      next: function () {
        const result = {
          value: self.store[index],
          done: index >= self.store.length
        }
        index++
        return result
      }
    }
  }
}

for (const item of obj) {
  console.log('Circulatory body', item)
}

Iterator pattern (one of the design patterns)

Another major use of iterators: Iterator mode

Gernator generator

reference resources: js single thread mechanism and asynchronous programming (Promise, Generator, Async, Await)

ES Modules

reference resources: ES Modules/CommonJS/AMD/CMD in Engineering

New features in ES2016

Include method of array

// Array.prototype.includes -----------------------------------

const arr = ['foo', 1, NaN, false]

// Find return element subscript
console.log(arr.indexOf('foo'))
// Cannot find return - 1
console.log(arr.indexOf('bar'))
// Cannot find NaN in array
console.log(arr.indexOf(NaN))

// Directly returns whether the specified element exists
console.log(arr.includes('foo'))
// Ability to find NaN
console.log(arr.includes(NaN))

Exponential operator

// Exponential operator---------------------------------------------------

console.log(Math.pow(2, 10))

console.log(2 ** 10)

New features in ES2017

Object adding method

Object.values -- similar to object Keys, return the value array of the object
Object.entries -- returns the key value pairs in the object in the form of an array. Combined with for... Of, you can traverse obj

const obj = {
  foo: 'value1',
  bar: 'value2'
}

// Object.values -----------------------------------------------------------

console.log(Object.values(obj))

// Object.entries ----------------------------------------------------------

console.log(Object.entries(obj))
// It is simpler than iterator. First convert obj into an array, and then use for of
for (const [key, value] of Object.entries(obj)) {
  console.log(key, value)
}

console.log(new Map(Object.entries(obj)))

Object.getOwnPropertyDescriptors -- get the complete information of object properties, which is mainly used in conjunction with get and set in ES5
Object.assign failed to get set and get information

const p1 = {
  firstName: 'Lei',
  lastName: 'Wang',
  get fullName () {
    return this.firstName + ' ' + this.lastName
  }
}

// console.log(p1.fullName)

// const p2 = Object.assign({}, p1)
// p2.firstName = 'zce'
// console.log(p2)

const descriptors = Object.getOwnPropertyDescriptors(p1)
// console.log(descriptors)
const p2 = Object.defineProperties({}, descriptors)
p2.firstName = 'zce'
console.log(p2.fullName)

String new method

String.prototype.padStart / String.prototype.padEnd

const books = {
  html: 5,
  css: 16,
  javascript: 128
}

// for (const [name, count] of Object.entries(books)) {
//   console.log(name, count)
// }

for (const [name, count] of Object.entries(books)) {
  console.log(`${name.padEnd(16, '-')}|${count.toString().padStart(3, '0')}`)
}

Add trailing comma to function parameter

const arr = [
  100,
  200,
  300,
  400,
]
const arr = [
  100,
  200,
  300
]

New Async/Await asynchronous programming syntax

reference material: ecma6.0 English Specification
From ES2017 standard; async and await are more convenient for asynchronous programming, and usually need to be used in pairs;

1. Where async and await are upgraded compared with generate functions:

  • (1) Built in actuator
  • (2) Better semantics
  • (3) Better extender
  • (4) The return value is promise

2. Return values of async and await

  • (1) The return value of async is promise object; However, it should be noted that:

1. The async function returns a Promise object.
2. The value returned by the return statement inside the async function will become the parameter of the then method callback function.

async function f() {
  return 'hello world';
}

f().then(v => console.log(v))
// "hello world"
  • (2) The return value of await varies according to the following parameters. There are two types;

3. Parameters after await

  • (1) await is followed by a promise object; = > Return the result of promise object;
  • (2) await is followed by a value; = > Directly return the value;

4. Error handling method

If the Promise asynchronous operation after await fails, the Promise object equivalent to that returned by async function will be reject ed. It's best to put the await command in the try... catch code block

async function f() {
  await new Promise(function (resolve, reject) {
    throw new Error('Error ');
  });
}

f()
.then(v => console.log(v))
.catch(e => console.log(e))
async function myFunction() {
  try {
    await somethingThatReturnsAPromise();
  } catch (err) {
    console.log(err);
  }
}

// Another way of writing

async function myFunction() {
  await somethingThatReturnsAPromise()
  .catch(function (err) {
    console.log(err);
  });
}

5. Processing of concurrent / cyclic asynchronous requests

(1) If the asynchronous request is executed serially, it needs to wait synchronously, which will be time-consuming;

let foo = await getFoo();
let bar = await getBar();

// 1. Serial execution in the loop:
async function dbFuc(db) {
  let docs = [{}, {}, {}];

  for (let doc of docs) {
    await db.post(doc);
  }
}

// 2. Bad serial execution:? why? reflection? async in forEach should be executed asynchronously at the same time. Is there no await?
function dbFuc(db) { //async is not required here
  let docs = [{}, {}, {}];

  // May get wrong results
  docs.forEach(async function (doc) {
    await db.post(doc);
  });
}

(2) Parallel execution - wait for all responses before executing the next step;

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = await Promise.all(promises);
  console.log(results);
}

// Or use the following wording

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = [];
  for (let promise of promises) {
    results.push(await promise);
  }
  console.log(results);
}

(3) Parallel execution - do not wait for all responses, but call back one after another;

// You can not wait in for; Don't write it as a serial callback;
// Write asynchronous method calls in for? For example:

  let docs = [{}, {}, {}];

  for (let doc of docs) {
    db.post(doc).then((res)=>{});
  }

6. Async and await principles (using generator to realize async and await)

async and await are encapsulated in the bottom layer, and the code implementation is invisible
You can use the iterator or generator function to encapsulate the implementation; Reference code: (to be continued)

Data types defined before ES2019: 8

6 + 1 original data types + bigInt (next version)

  1. null
  2. undefined
  3. number
  4. string
  5. boolean
  6. Symbol(ES2015)
  7. BigInt(stage-4, the next version will be standardized)

1 reference data type
Object

Special thanks: lagoon education front-end high salary training camp

Keywords: Javascript Front-end ECMAScript

Added by shturm681 on Thu, 27 Jan 2022 16:00:50 +0200