An overview of the
ES is ECMAScript, a standardized scripting language developed by ECMA. The current version of ECMAScript used by JavaScript is ECMAScript-262.
The ECMAScript standard builds on existing technologies, most notably JavaScript (Netscape) and JScript (Microsoft). It was originally invented by Brendan Eich of Netscape and first appeared on Netscape Navigator 2.0. It appears on all browsers after Netscape 2.0 and Microsoft Internet Explorer 3.0.
ECMAScript version | Release time | The new features |
---|---|---|
ECMAScript 2009(ES5) | In November 2009 | Extended the functions of Object, Array, and Function |
ECMAScript 2015(ES6) | In June 2015 | Class, modularity, arrow functions, default values for function parameters, etc |
ECMAScript 2016(ES7) | In March 2016 | Includes, the index operator |
ECMAScript 2017(ES8) | In June 2017 | Sync /await, object.values (), object.entries (), String padding, etc |
Understanding these features can not only make our Coding more in line with the specification, but also improve our Coding efficiency.
The characteristics of the ES6
ES6 has a lot of features, and it was only standardized nearly six years after ES5 was released (2009-11 to 2015-6). There’s a lot of time between releases, so there are a lot of features in ES6.
Here are a few common ones:
- class
- modular
- Arrow function
- Default values for function arguments
- Template string
- Deconstruction assignment
- Extension operator
- Shorthand for object property
- Promise
- Let the Const
1. Class
For developers familiar with Java, Object-C, C # and other pure object-oriented languages, class will have a special feeling. ES6 introduced classes to make object-oriented programming in JavaScript much simpler and easier to understand.
class Animal {
// The constructor that will be called when instantiated, if not specified, will have a default constructor with no arguments.
constructor(name,color) {
this.name = name;
this.color = color;
}
// toString is a property on the stereotype object
toString() {
console.log('name:' + this.name + ',color:' + this.color); }}var animal = new Animal('dog'.'white');// Instantiate Animal
animal.toString();
console.log(animal.hasOwnProperty('name')); //true
console.log(animal.hasOwnProperty('toString')); // false
console.log(animal.__proto__.hasOwnProperty('toString')); // true
class Cat extends Animal {
constructor(action) {
// Subclasses must specify the super function in constructor, otherwise an error will be reported when creating an instance.
// Constructor with the default super function will be added if the top consructor is not set.
super('cat'.'white');
this.action = action;
}
toString() {
console.log(super.toString()); }}var cat = new Cat('catch')
cat.toString();
// the instance cat is an instance of cat and Animal, which is identical to Es5.
console.log(cat instanceof Cat); // true
console.log(cat instanceof Animal); // true
Copy the code
2. Module
ES5 does not support native modularity, and modules are added as an important part of ES6. The functions of the module mainly consist of export and import. Each module has its own scope. The calling relationship between modules is to specify the interfaces exposed by the module through export, and to refer to the interfaces provided by other modules through import. Namespaces are also created for modules to prevent naming conflicts for functions.
Export (export)
ES6 allows you to export multiple variables or functions within a module using export.
Export variables
//test.js
export var name = 'Rainbow'
Copy the code
Note: ES6 not only supports the export of variables, but also supports the export of constants. export const sqrt = Math.sqrt; // Export the constant
ES6 treats a file as a module that exports a variable through export. A module can also output multiple variables simultaneously.
//test.js
var name = 'Rainbow';
var age = '24';
export {name, age};
Copy the code
The export function
// myModule.js
export function myModule(someArg) {
return someArg;
}
Copy the code
Import (import)
Once the output of a module is defined, it can be referenced in another module by import.
import {myModule} from 'myModule';// main.js
import {name,age} from 'test';// test.js
Copy the code
Note: An import statement can import both default functions and other variables. import defaultMethod, { otherMethod } from ‘xxx.js’;
3. Arrow function
This is one of the most exciting features in ES6. => It’s not just shorthand for the keyword function, but it has other benefits as well. The arrow function shares the same “this” with the code surrounding it, which helps you solve the “this” problem. Experienced JavaScript developers are familiar with things like var self = this; Or var that = this. But with =>, you don’t need this model.
The structure of the arrow function
The arrow => of an arrow function is preceded by an empty parenthesis, a single argument name, or multiple argument names enclosed in parentheses. The arrow can be followed by an expression (as the return value of the function), or by the body of the function enclosed in curly braces (the value must be returned by return itself; otherwise, undefined).
// Example of the arrow function() = >1
v=>v+1
(a,b)=>a+b
()=>{
alert("foo");
}
e=>{
if (e == 0) {return 0;
}
return 1000/e;
}
Copy the code
Note: Both the arrow function and bind return a new function reference each time they are executed, so if you need the function reference to do something else (such as unmount a listener), you must keep the reference yourself.
Trap when uninstalling listeners
Wrong way
class PauseMenu extends React.Component{
componentWillMount(){
AppStateIOS.addEventListener('change'.this.onAppPaused.bind(this));
}
componentWillUnmount(){
AppStateIOS.removeEventListener('change'.this.onAppPaused.bind(this));
}
onAppPaused(event){
}
}
Copy the code
The right thing to do
class PauseMenu extends React.Component{
constructor(props){
super(props);
this._onAppPaused = this.onAppPaused.bind(this);
}
componentWillMount(){
AppStateIOS.addEventListener('change'.this._onAppPaused);
}
componentWillUnmount(){
AppStateIOS.removeEventListener('change'.this._onAppPaused);
}
onAppPaused(event){
}
}
Copy the code
In addition to the above, we can do the following:
class PauseMenu extends React.Component{
componentWillMount(){
AppStateIOS.addEventListener('change'.this.onAppPaused);
}
componentWillUnmount(){
AppStateIOS.removeEventListener('change'.this.onAppPaused);
}
onAppPaused = (event) = > {
// Define the function directly as a property of the arrow function, which is initialized with the this pointer bound}}Copy the code
Note that both bind and arrow functions return a new function reference each time they are executed, so if you need the function reference to do something else (such as unmount listeners), you must save the reference yourself.
4.Default values for function arguments
ES6 supports setting default values for functions when they are defined:
function foo(height = 50, color = 'red'{/ /... }Copy the code
Default values are not used:
function foo(height, color)
{
var height = height || 50;
var color = color || 'red'; / /... }Copy the code
This is usually fine, but it becomes problematic when the parameter’s Boolean value is false. For example, we call foo like this:
foo(0, "")
Copy the code
Since the Boolean value of 0 is false, the height will be 50. Similarly, the value of color is’ red ‘.
Therefore, function parameter defaults can not only make the code cleaner but also avoid some problems.
5. Template characters
ES6 supports template strings, which makes concatenation of strings more concise and intuitive.
Do not use template strings:
var name = 'Your name is ' + first + ' ' + last + '. '
Copy the code
Using a template string:
var name = `Your name is ${first} ${last}. `Copy the code
String concatenation is done in ES6 with ${}, just by putting variables in curly braces.
6.Deconstruction assignment
Destruct assignment syntax is an expression in JavaScript that allows you to quickly extract values from an array or object and assign them to a defined variable.
Gets the value in the array
We get values from the array and assign them to variables in the order that corresponds to the order of objects in the array.
var foo = ["one"."two"."three"."four"];
var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"Var [first,,, last] = foo; console.log(first); //"one"
console.log(last); // "four"// You can also write var a, b; [a, b] = [1, 2]; console.log(a); // 1 console.log(b); / / 2Copy the code
If you don’t get a value from the array, you can set a default value for the variable.
var a, b; [a=5, b=7] = [1]; console.log(a); // 1 console.log(b); / / 7Copy the code
Deconstructing assignments makes it easy to exchange the values of two variables.
var a = 1; var b = 3; [a, b] = [b, a]; console.log(a); // 3 console.log(b); / / 1Copy the code
Gets the value in the object
const student = {
name:'Ming',
age:'18',
city:'Shanghai'
};
const {name,age,city} = student;
console.log(name); // "Ming"
console.log(age); // "18"
console.log(city); // "Shanghai"
Copy the code
7. Spread operator
The extension operator… Array expressions or strings can be expanded syntactically during function calls/array construction; You can also expand an object expression as a key-value when an object is constructed.
grammar
Function call:
myFunction(... iterableObj);Copy the code
An array construct or string:
[...iterableObj, '4'.'hello'6];Copy the code
Cloning or copying properties when constructing objects (new to the ECMAScript 2018 specification) :
letobjClone = { ... obj };Copy the code
Application scenarios
Use the extension operator when a function is called
function sum(x, y, z) {
returnx + y + z; } const numbers = [1, 2, 3]; // Do not use the extension operator console.log(sum. Apply (null, numbers)); // Use the extension operator console.log(sum(... numbers)); / / 6Copy the code
Constructing an array
Push, splice, concat, and other methods can be used to make the elements of an existing array part of a new array without expansion syntax. With the expansion syntax, constructing new arrays becomes simpler and more elegant:
const stuendts = ['Jine'.'Tom'];
const persons = ['Tony'. stuendts,'Aaron'.'Anna'];
conslog.log(persions)// ["Tony"."Jine"."Tom"."Aaron"."Anna"]
Copy the code
Similar to the argument list expansion,… It can be used multiple times in any location when constructing a word group.
Copy an array
var arr = [1, 2, 3]; var arr2 = [...arr]; // equivalent to arr.slice() arr2.push(4); console.log(arr2)//[1, 2, 3, 4]Copy the code
The expansion syntax behaves the same as object.assign (), executing a shallow copy (traversing only one level).
Concatenating arrays
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; var arr3 = [...arr1, ...arr2]; Var arr4 = arR1.concat (arR2); var arr4 = arR1.concat (arR2);Copy the code
Extended operators have added support for objects in ECMAScript 2018
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 }; var clonedObj = { ... obj1 }; // The cloned object: {foo:"bar", x: 42 } var mergedObj = { ... obj1, ... obj2 }; // The merged object: {foo:"baz", x: 42, y: 13 }
Copy the code
Application in React
Usually when we encapsulate a component, we expose props to implement the functionality. Pass props that should be displayed externally in most cases. But when passing a large number of props can be tedious, we can use… (the extension operator, which retrives all the traversable properties of the parameter object).
Normally we would write it like this
<CustomComponent name ='Jine' age ={21} />
Copy the code
The use of… That’s the same thing as the above
const params = {
name: 'Jine', age: 21 } <CustomComponent {... params} />Copy the code
Cooperate with destruct assignment to avoid passing unnecessary parameters
var params = {
name: '123',
title: '456'.type: 'aaa'
}
var { type. other } = params; <CustomComponenttype='normal'number={2} {... Other} /> // Is equivalent to <CustomComponenttype='normal' number={2} name='123' title='456' />
Copy the code
8. Shorthand for object properties
ES6 allows you to set a property of an object without specifying the property name.
Do not use the ES6
const name='Ming',age='18',city='Shanghai'; const student = { name:name, age:age, city:city }; console.log(student); //{name:"Ming", age: "18", city: "Shanghai"}
Copy the code
Objects must contain properties and values, which is very redundant.
Use the ES6
const name='Ming',age='18',city='Shanghai'; const student = { name, age, city }; console.log(student); //{name:"Ming", age: "18", city: "Shanghai"}
Copy the code
Object, which is very concise.
9.Promise
Promise is a more elegant solution to asynchronous programming than the traditional callback solution. It was first proposed and implemented by the community, and ES6 wrote it into the language standard, unifying usage and providing Promise objects natively.
Do not use the ES6
Nest two setTimeout callbacks:
setTimeout(function()
{
console.log('Hello'); // Output after 1 second"Hello"
setTimeout(function()
{
console.log('Hi'); // Output after 2 seconds"Hi"
}, 1000);
}, 1000);
Copy the code
Use the ES6
var waitSecond = new Promise(function(resolve, reject)
{
setTimeout(resolve, 1000);
});
waitSecond
.then(function()
{
console.log("Hello"); // Output after 1 second"Hello"
return waitSecond;
})
.then(function()
{
console.log("Hi"); // Output after 2 seconds"Hi"
});
Copy the code
The above code uses two THEN’s for asynchronous programming serialization, avoiding callback hell:
10. Support let and const
Previously, JS did not have a block-level scope. Const and let fill this convenient gap. Const and let are block-level scopes.
Variables defined using var are at function level scope:
{ var a = 10; } console.log(a); / / output 10Copy the code
Variables defined with let and const are block-level scoped:
{
leta = 10; } console.log(a); //-1 or Error "ReferenceError: a is not defined"Copy the code
The characteristics of the ES7
After ES6, ES releases were more frequent, roughly once a year, so since ES6, the number of features per new release has been relatively small.
- includes()
- Exponential operator
1. Array.prototype.includes()
The includes() function determines whether an array contains a specified value, returning true if it does, and false otherwise.
The includes function is similar to indexOf. The following two expressions are equivalent:
arr.includes(x)
arr.indexOf(x) >= 0
Copy the code
Next, we determine whether the number contains an element:
What we did before ES7
Use indexOf() to verify the presence of an element in the array, depending on whether the return value is -1:
let arr = ['react'.'angular'.'vue'];
if (arr.indexOf('react') !== -1)
{
console.log('the react there');
}
Copy the code
Use ES7 includes()
Use includes() to verify the presence of an element in the array for a more intuitive purpose:
let arr = ['react'.'angular'.'vue'];
if (arr.includes('react'))
{
console.log('the react there');
}
Copy the code
2. Exponential operator
In ES7, the exponent operator ** was introduced, ** has the same function as math.pow (..) Equivalent calculation result.
Do not use the exponential operator
Use the custom recursive function calculateExponent or math.pow () to calculate the exponent:
function calculateExponent(base, exponent)
{
if (exponent === 1)
{
return base;
}
else
{
returnbase * calculateExponent(base, exponent - 1); } } console.log(calculateExponent(2, 10)); // Output 1024 console.log(math.pow (2, 10)); / / output 1024Copy the code
Use the exponential operator
Use the exponent operator **, just like the +, -, and so on:
console.log(2**10); / / output 1024Copy the code
The characteristics of ES8
- async/await
- Object.values()
- Object.entries()
- String padding
- A comma is allowed at the end of the function argument list
- Object.getOwnPropertyDescriptors()
Browser Compatibility
1.async/await
ES8 has added support for async/await, also known as asynchronous functions, which is a useful feature. Async /await frees us from the headache of callback hell and makes the whole code look neat.
The difference between using async/await and not using async/await:
login(userName) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('1001');
}, 600);
});
}
getData(userId) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (userId === '1001') {
resolve('Success');
} else {
reject('Fail'); }}, 600); }); } // Do not use async/await ES7doLogin(userName) {this.login(userName).then(this.getData).then(result => {console.log(result)}) ES8 asyncdoLogin2(userName) {
const userId=await this.login(userName);
const result=await this.getData(userId);
}
this.doLogin()// Success
this.doLogin2()// Success
Copy the code
Several application scenarios of async/await
Let’s look at several application scenarios of async/await.
Gets the return value of an asynchronous function
The asynchronous function itself returns a Promise, so we can get the return value of the asynchronous function by using then.
async function charCountAdd(data1, data2) {
const d1=await charCount(data1);
const d2=await charCount(data2);
return d1+d2;
}
charCountAdd('Hello'.'Hi').then(console.log); / / bythenGets the return value of an asynchronous function.function charCount(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data.length);
}, 1000);
});
}
Copy the code
Application of async/await in concurrent scenarios
For the example above, we call await twice, each time waiting 1 second for a total of 2 seconds, which is less efficient, and there is no dependency between the two calls of await. Can we make them execute concurrently? Yes, we can.
async function charCountAdd(data1, data2) {
const [d1,d2]=await Promise.all([charCount(data1),charCount(data2)]);
return d1+d2;
}
charCountAdd('Hello'.'Hi').then(console.log);
function charCount(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data.length);
}, 1000);
});
}
Copy the code
All accepts an array. Promise.all accepts an array of Promise objects and executes them concurrently.
Async /await error handling
Catch an error in the entire async/await function
async function charCountAdd(data1, data2) {
const d1=await charCount(data1);
const d2=await charCount(data2);
return d1+d2;
}
charCountAdd('Hello'.'Hi') .then(console.log) .catch(console.log); // Catch an error in the entire async/await function...Copy the code
This way you can catch errors that occur throughout charCountAdd’s run, either by charCountAdd itself, or by the calculation of Data1 or DatA2.
Second: Catch errors in a single await expression
async function charCountAdd(data1, data2) {
const d1=await charCount(data1)
.catch(e=>console.log('d1 is null'));
const d2=await charCount(data2)
.catch(e=>console.log('d2 is null'));
return d1+d2;
}
charCountAdd('Hello'.'Hi').then(console.log);
Copy the code
This way you can catch errors in each await expression. If you want to catch errors in both each await expression and the entire charCountAdd function, you can call charCountAdd with a catch.
. charCountAdd('Hello'.'Hi') .then(console.log) .catch(console.log); // Catch an error in the entire async/await function...Copy the code
Catch errors in multiple await expressions at the same time
async function charCountAdd(data1, data2) {
let d1,d2;
try {
d1=await charCount(data1);
d2=await charCount(data2);
}catch (e){
console.log('d1 is null');
}
return d1+d2;
}
charCountAdd('Hello'.'Hi')
.then(console.log);
function charCount(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data.length);
}, 1000);
});
}
Copy the code
2.Object.values()
Object.values() is a new function similar to object.keys (), but returns all the values of the property of the Object itself, excluding inherited values.
Suppose we want to traverse all the values of the following object obj:
const obj = {a: 1, b: 2, c: 3};
Copy the code
Do not use object.values () :ES7
const vals=Object.keys(obj).map(key=>obj[key]); console.log(vals); / / [1, 2, 3]Copy the code
Use the Object. The values () : ES8
const values=Object.values(obj1); console.log(values); / / [1, 2, 3]Copy the code
As you can see from the code above, object.values () saves us the step of going through keys and getting values from them.
3.Object.entries
The object.entries () function returns an array of key-value pairs for the enumerable properties of a given Object itself.
Next, let’s iterate over the keys and values of all properties of the obj object:
Do not use object.entries () :ES7
Object.keys(obj).forEach(key=>{
console.log('key:'+key+' value:'+obj[key]);
})
//key:a value:1
//key:b value:2
//key:c value:3
Copy the code
The use of the Object. Entries () : ES8
for(let [key,value] of Object.entries(obj1)){
console.log(`key: ${key} value:${value}`)
}
//key:a value:1
//key:b value:2
//key:c value:3
Copy the code
4.String padding
In ES8 two instances have been added to the String String. The function prototype. PadStart and String prototype. PadEnd, allows you to an empty String or other String is added to the beginning or end of the original String.
String.padStart(targetLength,[padString])
- TargetLength: the targetLength to which the current string is to be filled. If this value is less than the length of the current string, the current string itself is returned.
- PadString :(optional) padding a string. If the string is so long that the length of the filled string exceeds the target length, only the leftmost part is retained and the rest is truncated. The default value of this parameter is “”.
console.log('0.0'.padStart(4,'10')) / / 10.0 console. The log ('0.0'PadStart (20)) / / 0.00Copy the code
String.padEnd(targetLength,padString])
- TargetLength: the targetLength to which the current string is to be filled. If this value is less than the length of the current string, the current string itself is returned.
- PadString :(optional) padding a string. If the string is so long that the length of the filled string exceeds the target length, only the leftmost part is retained and the rest is truncated. The default value of this parameter is “”.
console.log('0.0'.padEnd(4,'0')) / / 0.00 console. The log ('0.0'.padEnd(10,'0'/ / 0.00000000))Copy the code
4. Allow a comma at the end of the function argument list
This is a painless update that is intended to make it easier to modify the same function when working with git for collaborative development without unnecessary row changes.
Do not use ES8
Var f =function(a, b ) { ... } // programmer B var f =function(a, b, // change line c // change line) {... } // programmer C var f =function(a, b, c, // change line d // change line) {... }Copy the code
Using ES8
Var f =function(a, b, ) { ... } // programmer B var f =function(a, b, c, // change line) {... } // programmer C var f =function(a, b, c, d, // change line) {... }Copy the code
5.Object.getOwnPropertyDescriptors()
Object. GetOwnPropertyDescriptors () function is used to retrieve an Object of all their property descriptors, if you don’t have any own properties, it returns null objects.
Function prototype:
Object.getOwnPropertyDescriptors(obj)
Copy the code
Returns a descriptor for all self properties of an obj object, or an empty object if there are none.
const obj2 = {
name: 'Jine',
get age() { return '18'}}; Object.getOwnPropertyDescriptors(obj2) // { // age: { // configurable:true,
// enumerable: true,
// get: function age(){}, //the getter function
// set: undefined
// },
// name: {
// configurable: true,
// enumerable: true,
// value:"Jine",
// writable:true
// }
// }
Copy the code
conclusion
The wheel of technology change is always moving forward, and the specification and standard of JavaScript are also being developed and perfected. You’ll find that many of the new ECMAScript features are already part of Typescript, browsers, or other polyfills. For example, ES8 async/await was incorporated into ECMAScript in June 2017. But I’ve been using these features since 2016, and they are often submitted by ECMAScript congressmen for inclusion in a future version of ECMAScript.
reference
- MDN
- ECMAScript ® 2016
- ECMAScript® 2016 language standard
- ECMAScript ® 2017