Recently, I made an internal share in the company to introduce the new features introduced after ES6 to the backend TL. Here I share the text and attach the PPT download link

πŸ“– post address: blog. Mitscherlich. Me / 2021/11 / es6…

Hello, everyone. Today I will introduce you to the syntax features and some practical apis added after ES6.

ECMAScript profile

What is the ECMAScript

ECMAScript is a scripting language specification defined by the International Standardization Organization ECMA. JavaScript is an implementation of ES;

ECMAScript (ES) is a specification defined by the International standardization Organization ECMA. ES is nothing new. After Netscape lost the browser wars, it donated its scripting language to ECMA and formed the Mozilla Foundation to participate in it. It can be said that JavaScript running in modern browsers is just an implementation of ES.

In addition to Chrome’s V8 engine being the most commonly used JS engine, Firefox and Apple’s Safari also have their own JS engine, and Node.js, the most frequently used front-end development engine, is based on V8.

We also see TypeScript a lot. TS was invented by Microsoft and can be easily understood as JavaScript with a type system, because it adds compiler type checking to JavaScript and supports the latest ES standard very well. So it’s usually recommended for large projects.

One of the biggest benefits TypeScript brings to development is type signatures. JS can also use JSDoc to annotate apis with type annotations, but this is not mandatory, and TS types are checked at compile time. In addition to giving developers the convenience of not having to click through the library to see the source details, this allows them to pass parameters more confidently, and avoids many implicit conversion problems with JS variables.

ECMAScript in relation to JavaScript/TypeScript

  • JavaScript is an implementation of the ECMAScript standard;
  • JavaScript is a scripting language (originally called LiveScript) originally developed and implemented by Brendan Eich and used in netscape browsers.
  • TypeScript is a programming language created by Microsoft. It can be understood as TypeScript = ECMAScript + Type Definition
  • TypeScript is typically adopted by large applications because it adds compile-time type checking to JavaScript and actively implements the ECMAScript standard.

What is ES6, ECMAScript 2015

We often hear nouns like ES6 and ES2015, which refer to the version of THE ES specification. For example, ES6 refers to the sixth edition of the ES standard, which can be likened to JDK 6. ES2015 means the standard was released in 2015. After that, the ES standard has been updated to ES2021, or ES12, at a rate of one major release per year.

  • ES versions have two public names: ES + version number or ES + Release year:
    • For example, if ES6 was released in 2015, ES6 = ES2015 = ECMAScript 2015;
    • Before this, there were ES3 and ES5 standards, but ES6 introduced the most features since its invention, so it is particularly important.

New syntax/keywords

New keywords:let

  • letUsed to declare a variable;
  • Basic usage:
let a = 1;
let b = a;

b = 2; // The face of the let declaration can be reassigned

console.log(a); / / = = = > 1
console.log(a); / / = = = > 2
Copy the code

let 与 varThe similarities and differences

  • Similarities:
    • let/varAre used to declare variables,constUsed to declare constants;
  • Difference:
    • letDeclared variables have temporary dead zones (TDZ);
    • letVariables declared have block-level scope and cannot be declared repeatedly in block-level scope;
    • varDeclared variables have variable promotion properties and can be accessed outside the block-level scope, even before they are declared.varVariables can be declared repeatedly;
    • In the non-strict mode,varVariables can be declared in a global scope;

Variable/function promotion: variables declared with var are promoted to the top of the function scope.

function foo() {
  console.log(a); // ===> undefined

  if (true) {
    var a = 1;

    console.log(a); / / = = = > 1}}Copy the code
  • Variable/function promotion for: usevarThe declared variable is promoted to the top of the function scope
function tribonacci(n) {
  if (n == 0) return 0;
  if (n <= 2) return 2;
  return tribonacci(n - 2) + tribonacci(n - 1);
}
Copy the code

This is equivalent to the following form:

var tribonacci;

tribonacci = function (n) {
  if (n == 0) return 0;
  if (n <= 2) return 2;
  return tribonacci(n - 2) + tribonacci(n - 1);
};
Copy the code

Problems caused by variable/function promotion:

  1. Variables cover each other;
var message = 'hello world';

function foo() {
  console.log(message);

  if (false) {
    // even falsy
    var message = 'bad apple! ';
  }
}

foo(); // print what ???
Copy the code
  1. Variable life extended, not immediately destroyed
for (var i = 0; i < 5; i++) {
  continue;
}

console.log(i); // print what ???
Copy the code

New keywords:class

Class is used to define a class in JavaScript, essentially a syntactic sugar wrapped around Prototype;

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

  great(message) {
    console.log(`hi there, I'm The ${this.name}. ${message}`); }}const bob = new Person('Bob');

bob.great('Never gonna give you up! ');
Copy the code

Before ES6, we had to customize types based on Function and Prototype:

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

Person.prototype.great = function (message) {
  console.log(`hi there, I'm The ${this.name}. ${message}`);
};

const bob = new Person('Bob');

bob.great('Never gonna let you down! ');
Copy the code

Search baidu or Google, a classic question is how to use JS to implement inheritance:

With class, we can easily implement inheritance using the extends keyword:

class Person {
  constructor(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex; }}class Student extends Person {
  constructor(name, age, sex, major) {
    super(name, age, sex); // Use the super keyword function to call the superclass constructor

    this.major = major; }}const alice = new Student('Alice'.21.'female'.'CS');

alice instanceof Person; // ===> true
Copy the code

The above example is equivalent to using Function + Prototype to implement inheritance;

function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}

function Student(name, age, sex, major) {
  Person.call(this, name, age, sex);

  this.major = major;
}

Student.prototype = new Person();
Student.prototype.constructor = Student;
Copy the code

New keywords:async + await

Async is used to modify a function so that it executes internally into an await await statement and then executes downwards.

Here’s a concrete example of how to implement a sleep function with async/await. There’s a little bit of Promise here, and we’ll talk about it:

const sleep = (ms) = > new Promise((resolve) = > setTimeout(resolve, ms));

async function foo() {
  console.log('Before sleep');
  await sleep(3 * 1000); // sleep for 3s
  console.log('After sleep');
}
Copy the code

Let’s take a look at how to implement the same function based on the callback form:

const sleep = (ms, cb) = > setTimeout(cb, ms);

function bar() {
  console.log('Before sleep');
  sleep(3000.() = > {
    // but in callback
    console.log('After sleep');
  });
}
Copy the code

The sleep function executes the cb callback after setTimeout, continuing the logic after sleep in the bar function.

Resolve (sleep) is called and await (await) is used: Wait for a synchronous operation to return, or wait for a Promise settle;

New syntax: arrow function

Basic usage:

  • Define a function:
const foo = (param) = > {
  console.log('bar', param);
};
Copy the code
  • Return an expression directly:
const toArray = (val) = > (Array.isArray(val) ? val : [val]);
Copy the code

withfunctionDefine the difference between functions

  • usefunctionFunctions defined by keywords also have promotion properties;
  • usefunctionThe keyword defines the function in the contextthisChanges as the caller changes;

To take a concrete example, suppose we have the following function definition:

'use strict';

function outer() {
  var outer_this = this;

  console.log('outer this', outer_this); // what will print ?

  function inner() {
    var inner_this = this;

    console.log('inner this', inner_this); // what will print ?

    // is this true ?
    console.log('outer this == inner this', outer_this == inner_this);
  }

  inner();
}
Copy the code

Consider the result of the following expression based on the above function definition

outer(); // There is no specific caller

const kt = {};

kt.outer = outer;

kt.outer(); // the 'kt' object acts as the caller

setTimeout(kt.outer, 3000); // Is the actual caller 'kt' or 'window'?
Copy the code

Next, we use the arrow function to rewrite the function definition:

'use strict';

const outer = () = > {
  var outer_this = this;

  console.log('outer this', outer_this); // always `undefined`

  const inner = () = > {
    var inner_this = this;

    console.log('inner this', inner_this); // always `undefined`

    // always be `true`
    console.log('outer this == inner this', outer_this == inner_this);
  };

  inner();
};
Copy the code

This pointer is no longer affected by the function caller, and always looks like what we expected when we developed it.

Alternatively, you can use the new ES6 function bind to bind this:

const bounded_fn = outer.bind(null);
Copy the code

Note, however, that bind has no effect on functions declared as arrow functions, and its context still points to the call stack at write time.

New syntax: Deconstruct assignment

  • To destruct an object:
const bob = { name: 'Bob'.girlfriend: 'Alice' };

const { girlfriend } = bob;
Copy the code
  • To destruct an array:
const [a1, a2] = [1.2.3]; // a1 == 1, a2 == 2
Copy the code

Destruct arrays to easily swap the values of two variables without the need for a third variable:

let x = 1,
  y = 2;

[x, y] = [y, x];

console.log(x, y); 1 / / 2
Copy the code
  • A common usage scenario:
function fetchUserList({ clinicId }) {
  return axios({
    url: '/api/user/list'.params: { clinicId },
  });
}

const {
  userList = [], // If the deconstructed variable is undefined, the default value can be set here
} = await fetchUserList(clinicVo); // Assume that a key in clinicVo is clinicId
Copy the code

New syntax: expansion operator

The expansion syntax can expand an object/array/string key-value or positional argument at the level of function arguments:

  • Expand an object
const obj = { name: 'foo' };
constobj_clone = { ... obj };console.log(obj_clone); // { name: 'foo' }
console.log(obj == obj_clone); // false
Copy the code
  • Expand an array
const arr = [1.2.3];
const arr2 = [...arr]; / / similar to arr. Slice ()
console.log(arr == arr2); // false
arr2.push(4); // Operations on ARR2 do not affect ARR
console.log(arr, arr2); // [1, 2, 3] [1, 2, 3, 4]
Copy the code
  • Expansion function parameters are positional parameters
const sum = (x, y, z) = > x + y + z;

const nums = [1.2.3];

console.log(sum(... nums));/ / 6
Copy the code

A common usage scenario is merging objects/arrays:

  • Merge two arrays, similarArray.concat:
const arr1 = [1.2.3];
const arr2 = [4.5.6];

const arr = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
Copy the code
  • Merge two objects, similar toObject.assignIn the object after the same fieldvalueWill cover the front:
const obj1 = { name: 'obj1'.foo: 1 };
const obj2 = { name: 'obj2'.bar: 'baz' };

constobj = { ... obj1, ... obj2 };// { name: 'obj2', foo: 1, bar: 'baz' }
Copy the code

New syntax:for .. ofstatements

for .. The of statement allows loop calls to each item on any iterable (Array, Map, Set, String, etc.) :

Basic usage

const arr = [1.2.3];

for (const item of arr) {
  console.log(item); // Final output: 1, 2, 3
}
Copy the code

This example is formally equivalent to:

const arr = [1.2.3];

for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}
Copy the code

withforLoop statement,for .. inStatements,forEachDifferences in methods:

  • for .. inAn Enumerable property for an object;
  • forEachMethods can be implemented in anyforEachObject, for example:NodeList;
  • for .. ofAvailable only in with[Symbol.iterator]Property used on the object;
Array.prototype.customKey = 'kt';

const array = [1.2.3];

for (const k in array) {
  console.log(k, '- >', array[k]); Final output: 0 -> 1 1 -> 2 2 -> 3 customKey -> kt
}

for (const i of array) {
  console.log(i); // Final output: 1, 2, 3
}
Copy the code

Other New syntax

Short for object properties (properties, methods)

const data = { name: 'kt' };

const kt = {
  data, // Equivalent to data: data

  init() {
    Function () {/*... * /} equivalence
    // ...}};Copy the code

Template string

  • Single-line text
const api_url = `/api/code? cat=${cat || 'HBO'}`;
Copy the code
  • Multiline text
const template = ` 
      

hello world

Template string is very useful
`
; Copy the code

Optional chain? .

  • Take property
constdata = response? .data;/ / equivalent to the
constdata = response ! =null ? response.data : undefined;
Copy the code
  • The technique
constresult = object.method? . ();/ / equivalent to the
constresult = object.method ! =null ? object.method() : undefined;
Copy the code

Null value merge??

constdata = response? .data ?? defaultData;/ / equivalent to the
constdata = response ! =null ? response.data : defaultData;
Copy the code
  • with||The difference between operators is,??Only if the lvalue isnull ζˆ– undefinedCome into effect when; while||Operator false at lvalue (0.' '.false.null.undefined), return an rvalue:
// Suppose we have a response = {data: 0}, defaultData = 1
const data = response.data ?? defaultData; // This is the case
/ / if use | | operators, may not be able to return in line with expectations
const data = response.data || defaultData; // Return defaultData 1
Copy the code

Iterator function

function* makeGenerator(. args) {
  for (const arg of args) {
    yieldarg; }}const g = makeGenerator(1.2.3);

let current;
while((current = g.next()).done ! =true) {
  console.log(current.value); // Final output: 1, 2, 3
}
Copy the code

New data class structure/type

The new type:Symbol

Symbol is the new base type in ES6, and can be understood simply as a globally unique constant;

Basic usage

const sym1 = Symbol(a);const sym2 = Symbol('foo');
const sym3 = Symbol('foo');

console.log(sym2 == sym3); // false
Copy the code

Note that Symbol can only be used as a wrapper type and cannot be called by the new operation:

const sym = new Symbol(a);// TypeError
Copy the code

New object:Map

A Map is similar to a HashMap in Java. It is used to store data in key-value format. The Key may not be a string.

Basic usage

const map = new Map(a); map.set('name'.'foo'); // Key can also be string
map.set(1.'bar'); // Can also be number
map.set(Symbol('map.foo'), 'baz'); // We can also use symbol
map.set({ name: 'kt' }, 'kt'); // Even object

const size = map.size;

for (const [key, value] of map) {
  console.log(key, '= = >', value);
}
// name ==> foo
// 1 ==> bar
// Symbol(map.foo) ==> baz
// { name: 'kt' } ==> kt
Copy the code

Map 与 ObjectThe similarities and differences

  • Similarities:
    • Both can store data in key-value form.
  • Difference:
    • MapKey can be any value,ObjectThe key can only bestring ζˆ– symbol;
    • MapThe key of is ordered,ObjectKey is unordered before ES6;
    • MapCan be achieved byfor .. ofTraverse,ObjectOnly throughfor .. inOr passObject.keysTraversal after obtaining all keys;
    • MapPerformance is better in the case of frequent key-value pair additions and deletions.ObjectDependence and optimization of JS engine itself;

New object:Map

Set is basically the same as Set

in Java. It is used to store non-repeating data.

Basic usage

const set = new Set(a); set.add(1); // Set(1) { 1 }
set.add(5); // Set(2) { 1, 5 }
set.add(5); // Set(2) { 1, 5 }
set.add('foo'); // Set(3) { 1, 5, 'foo' }
const o = { a: 1.b: 2 };
set.add(o); // Set(4) { 1, 5, 'foo', { a: 1, b: 2 } }
set.add({ a: 1.b: 2 }); // Set(5) { 1, 5, 'foo', { a: 1, b: 2 }, { a: 1, b: 2 } }
Copy the code

Common use

  • Array to heavy
const arr = [1.2.2.undefined.3.4.5.undefined.null];

const set = new Set(arr);

const uniqed_arr = [...set]; // [ 1, 2, undefined, 3, 4, 5, null ]
Copy the code

New global variable:Promise

A Promise is a special type that represents the completion state and result value of an asynchronous operation. You can think of a Promise as a finite state machine:

A Promise must be in one of the following states:

  • Pending: Initial state, neither honored nor rejected.
  • This is a big pity.: indicates that the operation completed successfully.
  • I have rejected the offer.: Indicates that the operation fails.

At this point, let’s review the previous implementation of the sleep function:

const sleep = (ms) = > new Promise((resolve) = > setTimeout(resolve, ms));

const foo = () = > {
  console.log('before sleep');
  sleep(3000).then(() = > {
    console.log('after sleep');
  });
};
Copy the code

It is not difficult to see that when setTimeout ends, the promisor. resolve method is called, making the Promise returned by sleep function enter the depressing state, so that the then callback function can be entered to continue to complete the subsequent logic of the outer function.

Promise chain call

const fetchUserList = ({ clinicId }) = >
  axios
    .get('/api/user/list', {
      params: { clinicId },
    })
    .then(({ data: userList = [] }) = > userList);

const fetchClinicVo = (clinicCode) = >
  axios.get('/api/clinic', {
    params: { clinicCode },
  });

const userList = await fetchClinicVo(clinicCode).then(fetchUserList);
Copy the code

New common object, array API

Object.assign

For shallow merging multiple objects, return the application of the first argument:

const obj1 = { a: 1.b: 2 };
const obj2 = { c: 3.d: 4 };

const obj = Object.assign({}, obj1, obj2); // { a: 1, b: 2, c: 3, d: 4 }
Copy the code

It can also be used for shallow copies if only one object is passed:

const shallowClone = (obj) = > Object.assign({}, obj);

const objClone = shallowClone(obj);

console.log(objClone == obj); // false
Copy the code

Object.keys/Object.values

  • keys()Returns the names of all the enumerable properties of an object, usually used to traverse the object
const obj = { a: 1.b: 2.name: 'foo' };

console.log(Object.keys(obj)); // ['a', 'b', 'name']
Copy the code
  • values()Returns all values of an object in the same orderkeys()Return order:
console.log(Object.values(obj)); // [1, 2, 'foo']
Copy the code

Object.entries

Return all key-value pairs of an object:

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

Can be used for Object to Map conversion:

const map = new Map(pairs); // Map(3) { 'a' => 1, 'b' => 2, 'name' => 'foo' }
Copy the code

Array.some/Array.every

  • some()The Judge () method is used to determine if any elements in an array can pass the Judge () function:
const nums = [1.2.3.4.5];

/** * Determines whether any element in the array is greater than the given value *@params {number[]} arr
 * @params {number} target
 * @returns {boolean}* /
const isAnyGt = (arr, target) = > arr.some((t) = > t > target);

isAnyGt(nums, 3); // true
Copy the code
  • every()The check function is used to check whether each item in an array can pass the check function:
/** * Determines whether each item in the array is less than the given value *@params {number[]} arr
 * @params {number} target
 * @returns {boolean}* /
const isAllLt = (arr, target) = > arr.every((t) = > t < target);

isAllLt(nums, 10); // true
Copy the code

Array.find/Array.findIndex

  • find()The getElement () method is used to find a matching element in an array:
const currentUser = '1';

const userList = [
  { id: 0.name: 'admin'.defunct: false },
  { id: 1.name: 'bob'.defunct: false },
  { id: 2.name: 'alice'.defunct: true},];const currentUser = userList.find((user) = > user.id == currentUser);
Copy the code
  • findIndex()The index () method finds the index of a specified element in an array:
const currentUserIndex = userList.findIndex((user) = > user.id == currentUser);
Copy the code

Array.reduce

Use the reducer method to call once on each entry of the array and summarize the result into a single return value:

const accelerator = (sum, num) = > (sum += num);

const nums = [1.2.3];

console.log(nums.reduce(accelerator, 0)); / / 6
Copy the code

The above example uses for.. The of statement can be expressed as:

const nums = [1.2.3];

let sum = 0;

for (const num of nums) sum += num;
Copy the code

A more complicated example

const nodeList = [
{ id: 0.name: 'node0'.parent: null },
{ id: 1.name: 'node1'.parent: 0 },
{ id: 2.name: 'node2'.parent: 1 },
{ id: 3.name: 'node3'.parent: null },
{ id: 4.name: 'node4'.parent: 2 },
{ id: 5.name: 'node5'.parent: 1},];const tree = nodeList.reduce((tree, node) = > {
  if(node.parent ! =null) {
    const parent = findNodeById(tree, node.parent);
    if(! parent.children) { parent.children = []; } parent.children.push(node); }else {
    tree.push (node) ;
  }
  return tree;
}, []):

function findNodeById(tree, id) {
  let result = null;
  (function traverse(root) {
    for (const node of root) {
      const { children = [] } = node;
      if (children. length > 0) {
        traverse(children);
      }
      if (id === node. id && result == null) {
        result = node;
        break;
      }
  })(tree);
  return result;
}
Copy the code