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
let
Used 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
δΈ var
The similarities and differences
- Similarities:
let
/var
Are used to declare variables,const
Used to declare constants;
- Difference:
let
Declared variables have temporary dead zones (TDZ);let
Variables declared have block-level scope and cannot be declared repeatedly in block-level scope;var
Declared variables have variable promotion properties and can be accessed outside the block-level scope, even before they are declared.var
Variables can be declared repeatedly;- In the non-strict mode,
var
Variables 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: use
var
The 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:
- 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
- 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
withfunction
Define the difference between functions
- use
function
Functions defined by keywords also have promotion properties; - use
function
The keyword defines the function in the contextthis
Changes 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, similar
Array.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 to
Object.assign
In the object after the same fieldvalue
Will 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 .. of
statements
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
withfor
Loop statement,for .. in
Statements,forEach
Differences in methods:
for .. in
An Enumerable property for an object;forEach
Methods can be implemented in anyforEach
Object, for example:NodeList
;for .. of
Available 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
ζundefined
Come 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
δΈ Object
The similarities and differences
- Similarities:
- Both can store data in key-value form.
- Difference:
Map
Key can be any value,Object
The key can only bestring
ζsymbol
;Map
The key of is ordered,Object
Key is unordered before ES6;Map
Can be achieved byfor .. of
Traverse,Object
Only throughfor .. in
Or passObject.keys
Traversal after obtaining all keys;Map
Performance is better in the case of frequent key-value pair additions and deletions.Object
Dependence 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