Es7, es8 es9 new features
1. New ES7 features (ECMAScript 2016)
ES7 has two main additions to ES6:
- Array. The prototype. Includes () method
- Exponentiation operator (**)
Array. The prototype. Includes () method
The includes() method is used to determine whether an array contains a specified value, returning true if it does and false otherwise.
// ex
var array = [1.2.3];
console.log(array.includes(2));
// expected output: true
var pets = ['cat'.'dog'.'bat'];
console.log(pets.includes('cat'));
// expected output: true
console.log(pets.includes('at'));
// expected output: false
Copy the code
The array.prototype.includes () method takes two arguments:
-
The value to search for
-
The starting index of the search
When the second argument is passed in, the method searches backwards from the index (the default index value is 0). Return true if the search value exists in the array, false otherwise. Consider the following example:
// ex:
['a'.'b'.'c'.'d'].includes('b') // true
['a'.'b'.'c'.'d'].includes('b'.1) // true
['a'.'b'.'c'.'d'].includes('b'.2) // false
Copy the code
For the difference with indexOf, see the code
/ / ex1:
var ary = [1];
if (ary.indexOf(1)! = =- 1) {
console.log("Array exists 1")}if (ary.includes(1)) {
console.log("Array exists 1")}/ / ex2:
var ary1 = [NaN];
console.log(ary1.indexOf(NaN))/ / 1
console.log(ary1.includes(NaN))//true
/ / ex3:
var ary1 = new Array(3);
console.log(ary1.indexOf(undefined));/ / 1
console.log(ary1.includes(undefined))//true
Copy the code
Exponentiation operator (**)
Addition/subtraction we usually use the infix form, which is straightforward. In ECMAScript2016, we can use ** instead of Math.pow.
4 ** 3 / / 64
/ / equivalent to the
Math.pow(4.3)
// It is worth mentioning that as an infix operator, ** also supports the following operations
let n = 4;
n **= 3;
/ / 64
Copy the code
2. New ES8 features (ECMAScript 2017)
Key new features:
- Async Functions
Secondary new features:
- Object.values / Object.entries
- String padding
- Object.getOwnPropertyDescriptors()
- Function argument list and trailing comma in call
Async Functions
Async Functions are also called Async/Await. I believe everyone is familiar with this concept. Async/Await is a syntactic sugar for handling ASYNCHRONOUS JS operations that can help us get out of callback hell and write more elegant code.
Commonly understood, the async keyword is used to tell the compiler to treat calibrated functions differently. When the compiler encounters “await” keyword in the “await” function, it should stop running and wait until the “await” function has finished processing. If fulfiled, the function returns fulfillment Value, otherwise it gets Reject Value.
Here are a few common uses to make sense of them:
// ex:
async function asyncFunc() {
const result = await otherAsyncFunc();
console.log(result);
}
// Equivalent to:
function asyncFunc() {
return otherAsyncFunc()
.then(result= > {
console.log(result);
});
}
// The advantage is even greater when processing multiple asynchronous functions sequentially:
async function asyncFunc() {
const result1 = await otherAsyncFunc1();
console.log(result1);
const result2 = await otherAsyncFunc2();
console.log(result2);
}
// Equivalent to:
function asyncFunc() {
return otherAsyncFunc1()
.then(result1= > {
console.log(result1);
return otherAsyncFunc2();
})
.then(result2= > {
console.log(result2);
});
}
// parallel processing of multiple asynchronous functions:
async function asyncFunc() {
const [result1, result2] = await Promise.all([
otherAsyncFunc1(),
otherAsyncFunc2(),
]);
console.log(result1, result2);
}
// Equivalent to:
function asyncFunc() {
return Promise.all([
otherAsyncFunc1(),
otherAsyncFunc2(),
])
.then([result1, result2] => {
console.log(result1, result2);
});
}
// Handle error:
async function asyncFunc() {
try {
await otherAsyncFunc();
} catch (err) {
console.error(err); }}// Equivalent to:
function asyncFunc() {
return otherAsyncFunc()
.catch(err= > {
console.error(err);
});
}
Copy the code
Object.values and Object.entries
The object.values () method returns an array of all the enumerable property values of a given Object, in the same order as using for… The in loop has the same order (the difference is that for-In loops enumerate properties in the stereotype chain).
The obj parameter is the object to be operated on. It can be an object, or an array (an object with a numeric index, [10,20,30] -> {0: 10, 1:20, 2:30}).
// ex:
const obj = { x: 'xxx', y: 1 };
Object.values(obj); // ['xxx', 1]
const obj = ['e'.'s'.'8']; // equivalent to {0: 'e', 1: 's', 2: '8'};
Object.values(obj); // ['e', 's', '8']
// When we use numeric keys, we return numeric sort
// Sort by key
const obj = { 10: 'xxx'.1: 'yyy'.3: 'zzz' };
Object.values(obj); // ['yyy', 'zzz', 'xxx']
Object.values('es8'); // ['e', 's', '8']
Copy the code
The object. entries method returns an array of the given Object’s own traversable properties [key, value] sorted the same way as Object.values. The declaration of this method is trivial:
// ex:
const obj = { x: 'xxx', y: 1 };
Object.entries(obj); // [['x', 'xxx'], ['y', 1]]
const obj = ['e'.'s'.'8'];
Object.entries(obj); // [['0', 'e'], ['1', 's'], ['2', '8']]
const obj = { 10: 'xxx'.1: 'yyy'.3: 'zzz' };
Object.entries(obj); // [['1', 'yyy'], ['3', 'zzz'], ['10': 'xxx']]
Object.entries('es8'); // [['0', 'e'], ['1', 's'], ['2', '8']]
Copy the code
String padding
Added two functions to String: padStart and padEnd.
As their name suggests, the main purpose of these functions is to fill in the beginning and end of a string so that the resulting string length is the given length. You can fill it with a specific character, or a string, or a default space. Here is the declaration of the function:
str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])
Copy the code
The first argument to these functions is targetLength, which is the length of the resulting string. The second argument is the optional padString (padding character), a string used to populate the source string. The default value is space.
'es8'.padStart(2); // 'es8'
'es8'.padStart(5); // ' es8'
'es8'.padStart(6.'woof'); // 'wooes8'
'es8'.padStart(14.'wow'); // 'wowwowwowwoes8'
'es8'.padStart(7.'0'); // '0000es8'
'es8'.padEnd(2); // 'es8'
'es8'.padEnd(5); // 'es8 '
'es8'.padEnd(6.'woof'); // 'es8woo'
'es8'.padEnd(14.'wow'); // 'es8wowwowwowwo'
'es8'.padEnd(7.'6'); // 'es86666'
Copy the code
Object.getOwnPropertyDescriptors
GetOwnPropertyDescriptors method returns the specified object all its attributes describe objects. Property description objects are defined directly on the object, rather than inheriting from the object’s stereotype. The main motivation for adding this function in ES2017 is to make it easy to deeply copy one object to another, and to copy getters/setters. The statement is as follows:
Object.getOwnPropertyDescriptors(obj)
Copy the code
Obj is the object to be operated on. The returned description object key values are different, Enumerable, writable, get, set and value.
const obj = {
get es7() { return 777; },
get es8() { return 888; }};Object.getOwnPropertyDescriptors(obj);
/ / {
// es7: {
// configurable: true,
// enumerable: true,
// get: function es7(){}, //the getter function
// set: undefined
/ /},
// es8: {
// configurable: true,
// enumerable: true,
// get: function es8(){}, //the getter function
// set: undefined
/ /}
// }
Copy the code
At the end of a comma
The closing comma is very clear in code:
// When parameters are defined
function foo(param1, param2,) {}
// when a function is called
foo(
'abc'.'def',);/ / object
let obj = {
first: 'Jane',
last: 'Doe'};/ / array
let arr = [
'red'.'green'.'blue',];Copy the code
What are the benefits of this change?
- First, it’s easier to rearrange items because you don’t have to add and remove commas if the last item changes its position.
- Second, it helps version control systems track changes that actually occur. For example, from:
[
'foo'
]
Copy the code
Modified to
[
'foo'.'bar'
]
Copy the code
Causes line ‘foo’ and line ‘bar’ to be marked as changed, even though the only real change is when the latter line is added.
3, NEW ES9 features (ECMAScript 2018)
Key new features:
- Asynchronous iterative
- Rest/Spread properties
New regular expression features:
- RegExp named capture groups
- RegExp Unicode Property Escapes (Mathias Bynens)
- RegExp Lookbehind Assertions
Other new features:
- Promise.prototype.finally()
- Template String modification
Asynchronous iterative
First, let’s review synchronous iterators:
ES6 introduces synchronous iterators, which work as follows:
- Iterable: An object that represents the possibility of iterating through the symbol. iterator method.
- Iterator: An object returned by calling iterable [symbol.iterator] (). It wraps each iteration element in an object and returns one at a time through its next() method.
- IteratorResult: The object returned next(). The value attribute contains an iterated element, with the done attribute being the last element after true.
Example:
const iterable = ['a'.'b'];
const iterator = iterable[Symbol.iterator]();
iterator.next()
// { value: 'a'.done: false }
iterator.next()
// { value: 'b'.done: false }
iterator.next()
// { value: undefined, done: true }
Copy the code
Asynchronous iterator
The previous iteration approach was synchronous and did not apply to asynchronous data sources. For example, in the following code, readLinesFromFile() cannot pass its asynchronous data through synchronous iterations:
function readLinesFromFile (){
setTimeout((a)= > {
return "123456"
},1000)}for (const line of readLinesFromFile()) {
console.log(line);
}
function *createNumberIterator(){
yield 1;
yield 2;
yield 3;
}
const iterator = createNumberIterator();
const p2 = iterator.next(); // Object {value: 2, done: false}
const p3 = iterator.next(); // Object {value: 3, done: false}
const p4 = iterator.next(); // Object {value: undefined, done: true}
const p1 = iterator.next(); // Object {value: 1, done: false}
log(p1, p2, p3, p4)
Copy the code
Asynchronous iterators work much like regular iterators, but asynchronous iterators involve promises:
async function example() {
// Common iterator:
const iterator = createNumberIterator();
iterator.next(); // Object {value: 1, done: false}
iterator.next(); // Object {value: 2, done: false}
iterator.next(); // Object {value: 3, done: false}
iterator.next(); // Object {value: undefined, done: true}
// Asynchronous iterator:
const asyncIterator = createAsyncNumberIterator();
const p = asyncIterator.next(); // Promise
await p;// Object {value: 1, done: false}
await asyncIterator.next(); // Object {value: 2, done: false}
await asyncIterator.next(); // Object {value: 3, done: false}
await asyncIterator.next(); // Object {value: undefined, done: true}
}
Copy the code
The next() method of an asynchronous iterator object returns a Promise that resolves like a regular iterator. Iterator.next ().then(({value, done})=> {//{value: ‘some val’, done: false}}
const promises = [
new Promise(resolve= > resolve(1)),
new Promise(resolve= > resolve(2)),
new Promise(resolve= > resolve(3)),];async function test() {
for await (const p of promises) {
console.log(p);
}
}
test(); / / 1, 2, 3
Copy the code
Rest/Spread properties
This is what is commonly referred to as REST parameters and extension operators. This feature was introduced in ES6, but objects in ES6 are limited to arrays
restParam(1.2.3.4.5);
function restParam(p1, p2, ... p3) {
// p1 = 1
// p2 = 2
// p3 = [3, 4, 5]
}
const values = [99.100.- 1.48.16];
console.log( Math.max(... values) );/ / 100
Copy the code
In ES9, objects are provided with array-like REST arguments and extension operators:
const obj = {
a: 1,
b: 2,
c: 3
}
const{ a, ... param } = obj;console.log(a) / / 1
console.log(param) //{b: 2, c: 3}
function foo({a, ... param}) {
console.log(a); / / 1
console.log(param) //{b: 2, c: 3}
}
Copy the code
Regular expressions name capture groups
A numbered capture group
// Regular expressions name capture groups
const RE_DATE = / [0-9] {4}) - ([0-9] {2}) - ([0-9] {2}) /;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; / / 1999
const month = matchObj[2]; / / 12
const day = matchObj[3]; / / 31
Copy the code
Capturing groups by digital reference has several disadvantages:
- Finding the number of capture groups is a hassle: parentheses must be used.
- If you want to understand what groups are for, you need to look at regular expressions.
- If you change the order of the capture groups, you must also change the matching code.
Named capture group
In ES9, capture groups can be identified by name :(?
[0-9]{4})
Here, we mark the previous capture group year with a name. The name must be a valid JavaScript identifier (consider a variable name or attribute name). Once matched, you can access it by accessing the captured string matchobj.groups.year.
Let’s rewrite the previous code:
const RE_DATE = / (?
[0-9]{4})-(?
[0-9]{2})-(?
[0-9]{2})/
;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; / / 1999
const month = matchObj.groups.month; / / 12
const day = matchObj.groups.day; / / 31
// Destruct syntax is simpler
const {groups: {day, year}} = RE_DATE.exec('1999-12-31');
console.log(year); / / 1999
console.log(day); / / 31
Copy the code
You can see that naming capture groups has the following advantages:
- It is easier to find the “ID” of the capture group.
- The matching code becomes self-descriptive because the ID of the capture group describes what is being captured.
- If you change the order of the capture groups, there is no need to change the matching code.
- The names of the capture groups also make the regular expressions easier to understand because you can see directly what each group is used for.
Regular expression Unicode escape
This feature allows you to use \p{} to match characters by referring to Unicode character attributes inside braces, using the token U (Unicode) setting in regular expressions.
/^\p{White_Space}+$/u.test('\t \n\r')
// true
/^\p{Script=Greek}+$/u.test('mu epsilon tau ά')
// true
Copy the code
The new method matches Chinese characters
Since the Unicode Script for Chinese characters is Han, we can use this reg to match Chinese characters:
/[u4e00-u9fa5]/ [u4e00-u9fa5]/ [u4e00-u9fa5]/ [u4e00-u9fa5]/ [u4e00-u9fa5]
I randomly found a Chinese character “𬬭” added to Unicode8.0 on the Internet, and I tested the compatibility of the two regs:
oldReg=/[\u4e00-\u9fa5]/
newReg=/\p{Script=Han}/u
oldReg.test('abc')
// false
newReg.test('abc')
// false
oldReg.test(horizon)
// true
newReg.test(horizon)
// true
oldReg.test('𬬭')
// false
newReg.test('𬬭')
// true
Copy the code
Regular expression reverse assertion
Let’s see what regular expression preemptive assertions are:
For example, get the symbol of money
const noReLookahead = /\D(\d+)/,
reLookahead = /\D(? =\d+)/,
match1 = noReLookahead.exec('$123.45'),
match2 = reLookahead.exec('$123.45');
console.log(match1[0]); / / $123
console.log(match2[0]); / / $
Copy the code
In ES9 it is possible to allow reverse assertions:
const reLookahead = / (? <=\D)[\d\.]+/;
match = reLookahead.exec('$123.45');
console.log(match[0]); / / 123.45
Copy the code
Use? <= makes a reverse assertion, which can be used to get the price of the currency, ignoring the currency sign.
Promise.prototype.finally()
promise
.then(result= >{...}). The catch (error= >{...}). Finally,(a)= > {···});
Copy the code
Finally callback is always executed. Note that.finally() is not executed after.then or.catch
Template String modification
ES2018 removes syntactic restrictions on ECMAScript escaping sequences in tagged template strings. Previously, \u started a Unicode escape, \x started a hexadecimal escape, and \ followed by a number started an octal escape. This makes it impossible to create specific strings, such as the Windows file path C:\uuu\ XXX \111.
To remove syntactic restrictions on escape sequences, use the markup function String.raw before the template String:
`\u{54}`
// "T"
String.raw`\u{54}`
// "\u{54}"
Copy the code
More front-end dry goods content in the “daily learning front” wechat public number, welcome to pay attention to
reference
- The original document