以下是ECMAScript 2016、2017和2018中所有新增功能的示例

by rajaraodv

通过rajaraodv

以下是ECMAScript 2016、2017和2018中所有新增功能的示例 (Here are examples of everything new in ECMAScript 2016, 2017, and 2018)

It’s hard to keep track of what’s new in JavaScript (ECMAScript). And it’s even harder to find useful code examples.

很难跟踪JavaScript(ECMAScript)的新功能。 而且,找到有用的代码示例更加困难。

So in this article, I’ll cover all 18 features that are listed in the TC39’s finished proposals that were added in ES2016, ES2017, and ES2018 (final draft) and show them with useful examples.

因此,在本文中,我将介绍TC39最终提案中列出的全部18个功能,这些提案已添加到ES2016,ES2017和ES2018(最终草案)中,并通过有用的示例进行展示。

This is a pretty long post but should be an easy read. Think of this as “Netflix binge reading.” By the end of this, I promise that you’ll have a ton of knowledge about all these features.

这是一篇相当长的文章,但应该很容易阅读。 将此视为“ Netflix暴饮暴食”。 到此为止,我保证您将对所有这些功能有很多了解。

好,让我们一一介绍。 (OK, let’s go over these one by one.)

1. Array.prototype.includes (1. Array.prototype.includes)

includes is a simple instance method on the Array and helps to easily find if an item is in the Array (including NaN unlike indexOf).

includes是Array上的一个简单实例方法,可帮助轻松查找是否在Array中(包括与indexOf不同的NaN )。

Trivia: the JavaScript spec people wanted to name it contains , but this was apparently already used by Mootools so they used includes .

Trivia:人们希望将JavaScript规范命名为contains ,但Mootools显然已经使用了它,因此他们使用了includes

2.求幂中infix operator (2. Exponentiation infix operator)

Math operations like addition and subtraction have infix operators like + and - , respectively. Similar to them, the ** infix operator is commonly used for exponent operation. In ECMAScript 2016, the ** was introduced instead of Math.pow .

数学运算(例如加法和减法)分别具有中缀运算符(例如+- )。 与它们相似, ** infix运算符通常用于指数运算。 在ECMAScript 2016中,引入了**而不是Math.pow

1. Object.values() (1. Object.values())

Object.values() is a new function that’s similar to Object.keys() but returns all the values of the Object’s own properties excluding any value(s) in the prototypical chain.

Object.values()是一个类似于Object.keys()的新函数,但返回对象自身属性的所有值,但不包括原型链中的任何值。

2. Object.entries() (2. Object.entries())

Object.entries() is related to Object.keys , but instead of returning just keys, it returns both keys and values in the array fashion. This makes it very simple to do things like using objects in loops or converting objects into Maps.

Object.entries()Object.keys有关,但它不仅返回键,还以数组形式返回键和值。 这样就很容易执行诸如在循环中使用对象或将对象转换为Map之类的事情。

Example 1:

范例1:

Example 2:

范例2:

3.字符串填充 (3. String padding)

Two instance methods were added to String — String.prototype.padStart and String.prototype.padEnd — that allow appending/prepending either an empty string or some other string to the start or the end of the original string.

在String中添加了两个实例方法String.prototype.padStartString.prototype.padEnd允许将空字符串或其他字符串附加/添加到原始字符串的开头或结尾。

'someString'.padStart(numberOfCharcters [,stringForPadding]); 

'5'.padStart(10) // '         5'
'5'.padStart(10, '=*') //'=*=*=*=*=5'

'5'.padEnd(10) // '5         '
'5'.padEnd(10, '=*') //'5=*=*=*=*='
This comes in handy when we want to align things in scenarios like pretty print display or terminal print.
当我们想要在漂亮的打印显示器或终端打印等场景中对齐内容时,这非常方便。
3.1 padStart示例: (3.1 padStart example:)

In the below example, we have a list of numbers of varying lengths. We want to prepend “0” so that all the items have the same length of 10 digits for display purposes. We can use padStart(10, '0') to easily achieve this.

在下面的示例中,我们列出了不同长度的数字。 我们想在前面加上“ 0”,以便所有项目都具有相同的10位数字长度以用于显示。 我们可以使用padStart(10, '0')轻松实现这一目标。

3.2 padEnd示例: (3.2 padEnd example:)

padEnd really comes in handy when we are printing multiple items of varying lengths and want to right-align them properly.

当我们要打印长度不同的多个项目并希望正确对齐它们时, padEnd确实派上了用场。

The example below is a good realistic example of how padEnd , padStart , and Object.entries all come together to produce a beautiful output.

下面的示例是一个很好的现实示例,说明padEndpadStartObject.entries如何共同产生漂亮的输出。

const cars = {
  '🚙BMW': '10',
  '🚘Tesla': '5',
  '🚖Lamborghini': '0'
}

Object.entries(cars).map(([name, count]) => {
  //padEnd appends ' -' until the name becomes 20 characters
  //padStart prepends '0' until the count becomes 3 characters.
  console.log(`${name.padEnd(20, ' -')} Count: ${count.padStart(3, '0')}`)
});

//Prints..
// 🚙BMW - - - - - - -  Count: 010
// 🚘Tesla - - - - - -  Count: 005
// 🚖Lamborghini - - -  Count: 000
3.3表情符号和其他双字节字符上的⚠️padStart和padEnd (3.3 ⚠️ padStart and padEnd on Emojis and other double-byte chars)

Emojis and other double-byte chars are represented using multiple bytes of unicode. So padStart and padEnd might not work as expected!⚠️

表情符号和其他双字节字符使用多个字节的unicode表示。 所以padStart和padEnd可能无法按预期工作!⚠️

For example: Let’s say we are trying to pad the string heart to reach 10 characters with the ❤️ emoji. The result will look like below:

例如:假设我们正尝试使用❤️表情符号填充字符串的heart以使其达到10字符。 结果将如下所示:

//Notice that instead of 5 hearts, there are only 2 hearts and 1 heart that looks odd!
'heart'.padStart(10, "❤️"); // prints.. '❤️❤️❤heart'

This is because ❤️ is 2 code points long ('\u2764\uFE0F' )! The word heart itself is 5 characters, so we only have a total of 5 chars left to pad. So what happens is that JS pads two hearts using '\u2764\uFE0F' and that produces ❤️❤️. For the last one it simply uses the first byte of the heart \u2764 which produces ❤

这是因为❤️的长度为2个代码点( '\u2764\uFE0F' )! “ heart ”一词本身是5个字符,因此我们只剩下5个字符。 因此,发生的事是JS使用'\u2764\uFE0F'并且产生了❤️❤️。 对于最后一个,它仅使用心脏\u2764的第一个字节产生❤

So we end up with: ❤️❤️❤heart

所以我们最终得到了: ❤️❤️❤heart

PS: You may use this link to check out unicode char conversions.

PS:您可以使用此链接签出Unicode字符转换。

4. Object.getOwnPropertyDescriptors (4. Object.getOwnPropertyDescriptors)

This method returns all the details (including getter getand setter set methods) for all the properties of a given object. The main motivation to add this is to allow shallow copying / cloning an object into another object that also copies getter and setter functions as opposed to Object.assign .

此方法返回给定对象的所有属性的所有详细信息(包括getter get和setter set方法)。 添加它的主要动机是允许将对象浅复制/克隆到另一个对象中 这也复制了getter和setter函数,而不是Object.assign

Object.assign shallow copies all the details except getter and setter functions of the original source object.

Object.assign浅表会复制除原始源对象的getter和setter函数之外的所有详细信息。

The example below shows the difference between Object.assign and Object.getOwnPropertyDescriptors along with Object.defineProperties to copy an original object Car into a new object ElectricCar . You’ll see that by using Object.getOwnPropertyDescriptors ,discount getter and setter functions are also copied into the target object.

下面的示例显示了Object.assignObject.getOwnPropertyDescriptors以及Object.defineProperties之间的区别,该区别将原始对象Car复制到新对象ElectricCar 。 您将看到使用Object.getOwnPropertyDescriptorsdiscount getter和setter函数也被复制到目标对象中。

BEFORE…

之前…

AFTER…

后…

var Car = {
 name: 'BMW',
 price: 1000000,
 set discount(x) {
  this.d = x;
 },
 get discount() {
  return this.d;
 },
};

//Print details of Car object's 'discount' property
console.log(Object.getOwnPropertyDescriptor(Car, 'discount'));
//prints..
// { 
//   get: [Function: get],
//   set: [Function: set],
//   enumerable: true,
//   configurable: true
// }

//Copy Car's properties to ElectricCar using Object.assign
const ElectricCar = Object.assign({}, Car);

//Print details of ElectricCar object's 'discount' property
console.log(Object.getOwnPropertyDescriptor(ElectricCar, 'discount'));
//prints..
// { 
//   value: undefined,
//   writable: true,
//   enumerable: true,
//   configurable: true 
// }
//⚠️Notice that getters and setters are missing in ElectricCar object for 'discount' property !👎👎

//Copy Car's properties to ElectricCar2 using Object.defineProperties 
//and extract Car's properties using Object.getOwnPropertyDescriptors
const ElectricCar2 = Object.defineProperties({}, Object.getOwnPropertyDescriptors(Car));

//Print details of ElectricCar2 object's 'discount' property
console.log(Object.getOwnPropertyDescriptor(ElectricCar2, 'discount'));
//prints..
// { get: [Function: get],  👈🏼👈🏼👈🏼
//   set: [Function: set],  👈🏼👈🏼👈🏼
//   enumerable: true,
//   configurable: true 
// }
// Notice that getters and setters are present in the ElectricCar2 object for 'discount' property!

5. Add trailing commas in the function parameters (5. Add trailing commas in the function parameters)

This is a minor update that allows us to have trailing commas after the last function parameter. Why? To help with tools like git blame to ensure only new developers get blamed.

这是一个较小的更新,它使我们可以在最后一个函数参数之后使用逗号结尾。 为什么? 帮助诸如git blame之类的工具,以确保只有新开发人员受到指责。

The below example shows the problem and the solution.

以下示例显示了问题和解决方案。

Note: You can also call functions with trailing commas!
注意:您也可以使用尾随逗号来调用函数!

6.异步/等待 (6. Async/Await)

This, by far, is the most important and most useful feature if you ask me. Async functions allows us to not deal with callback hell and make the entire code look simple.

如果您问我,这是迄今为止最重要和最有用的功能。 异步函数使我们不必处理回调地狱,并使整个代码看起来很简单。

The async keyword tells the JavaScript compiler to treat the function differently. The compiler pauses whenever it reaches the await keyword within that function. It assumes that the expression after await returns a promise and waits until the promise is resolved or rejected before moving further.

async关键字告诉JavaScript编译器以不同的方式对待函数。 只要编译器在该函数中到达await关键字,它就会暂停。 它假定await之后的表达式返回一个promise,并等待直到promise被解决或被拒绝后再继续移动。

In the example below, the getAmount function is calling two asynchronous functions getUser and getBankBalance . We can do this in promise, but using async await is more elegant and simple.

在下面的示例中, getAmount函数正在调用两个异步函数getUsergetBankBalance 。 我们可以按承诺来做到这一点,但是使用async await更加优雅和简单。

6.1异步函数本身返回一个Promise。 (6.1 Async functions themselves return a Promise.)

If you are waiting for the result from an async function, you need to use Promise’s then syntax to capture its result.

如果您正在等待异步函数的结果,则需要使用Promise的then语法来捕获其结果。

In the following example, we want to log the result using console.log but not within the doubleAndAdd. So we want to wait and use then syntax to pass the result to console.log .

在下面的示例中,我们想使用console.log记录结果,而不是在doubleAndAdd中记录结果。 所以我们要等待, then使用语法将结果传递给console.log

6.2并行调用异步/等待 (6.2 Calling async/await in parallel)

In the previous example we are calling await twice, but each time we are waiting for one second (total 2 seconds). Instead we can parallelize it since a and b are not dependent on each other using Promise.all.

在前面的示例中,我们两次调用await,但是每次等待一秒钟(总计2秒)。 相反,我们可以并行化它,因为使用Promise.all可以使ab彼此不依赖。

6.3错误处理异步/等待功能 (6.3 Error handling async/await functions)

There are various ways to handle errors when using async await.

使用异步等待时,有多种处理错误的方法。

选项1-在函数中使用try catch (Option 1 — Use try catch within the function)
//Option 1 - Use try catch within the function
async function doubleAndAdd(a, b) {
 try {
  a = await doubleAfter1Sec(a);
  b = await doubleAfter1Sec(b);
 } catch (e) {
  return NaN; //return something
 }
return a + b;
}

//🚀Usage:
doubleAndAdd('one', 2).then(console.log); // NaN
doubleAndAdd(1, 2).then(console.log); // 6

function doubleAfter1Sec(param) {
 return new Promise((resolve, reject) => {
  setTimeout(function() {
   let val = param * 2;
   isNaN(val) ? reject(NaN) : resolve(val);
  }, 1000);
 });
}
选项2-捕获每个等待的表达式 (Option 2— Catch every await expression)

Since every await expression returns a Promise, you can catch errors on each line as shown below.

由于每个await表达式都返回一个Promise,因此您可以在每一行中捕获错误,如下所示。

//Option 2 - *Catch* errors on  every await line
//as each await expression is a Promise in itself
async function doubleAndAdd(a, b) {
 a = await doubleAfter1Sec(a).catch(e => console.log('"a" is NaN')); // 👈
 b = await doubleAfter1Sec(b).catch(e => console.log('"b" is NaN')); // 👈
 if (!a || !b) {
  return NaN;
 }
 return a + b;
}

//🚀Usage:
doubleAndAdd('one', 2).then(console.log); // NaN  and logs:  "a" is NaN
doubleAndAdd(1, 2).then(console.log); // 6

function doubleAfter1Sec(param) {
 return new Promise((resolve, reject) => {
  setTimeout(function() {
   let val = param * 2;
   isNaN(val) ? reject(NaN) : resolve(val);
  }, 1000);
 });
}
选项3-捕获整个异步等待功能 (Option 3 — Catch the entire async-await function)
//Option 3 - Dont do anything but handle outside the function
//since async / await returns a promise, we can catch the whole function's error
async function doubleAndAdd(a, b) {
 a = await doubleAfter1Sec(a);
 b = await doubleAfter1Sec(b);
 return a + b;
}

//🚀Usage:
doubleAndAdd('one', 2)
.then(console.log)
.catch(console.log); // 👈👈🏼<------- use "catch"

function doubleAfter1Sec(param) {
 return new Promise((resolve, reject) => {
  setTimeout(function() {
   let val = param * 2;
   isNaN(val) ? reject(NaN) : resolve(val);
  }, 1000);
 });
}
ECMAScript is currently in final draft and will be out in June or July 2018. All the features covered below are in Stage-4 and will be part of ECMAScript 2018.
ECMAScript目前处于最终草案中,将于2018年6月或7月发布。下面介绍的所有功能均在Stage-4中,并将成为ECMAScript 2018的一部分。
1. 共享内存和原子 (1. Shared memory and atomics)

This is a huge, pretty advanced feature and is a core enhancement to JS engines.

这是一个巨大的高级功能,是JS引擎的核心增强功能。

The main idea is to bring some sort of multi-threading feature to JavaScript so that JS developers can write high-performance, concurrent programs in the future by allowing to manage memory by themselves instead of letting JS engine manage memory.

主要思想是为JavaScript带来某种多线程功能,以便JS开发人员将来可以通过允许自己管理内存而不是让JS引擎管理内存来编写高性能的并发程序。

This is done by a new type of a global object called SharedArrayBuffer that essentially stores data in a shared memory space. So this data can be shared between the main JS thread and web-worker threads.

这是通过一种称为SharedArrayBuffer的新型全局对象完成的,该对象实际上将数据存储在共享 内存空间中 。 因此,可以在JS主线程和Web工作者线程之间共享此数据。

Until now, if we want to share data between the main JS thread and web-workers, we had to copy the data and send it to the other thread using postMessage . Not anymore!

到目前为止,如果要在JS主线程和Web工作者之间共享数据,则必须复制数据并使用postMessage将其发送到另一个线程。 不再!

You simply use SharedArrayBuffer and the data is instantly accessible by both the main thread and multiple web-worker threads.

您只需使用SharedArrayBuffer,主线程和多个Web工作者线程都可以立即访问数据。

But sharing memory between threads can cause race conditions. To help avoid race conditions, the “Atomics” global object is introduced. Atomics provides various methods to lock the shared memory when a thread is using its data. It also provides methods to update such data in that shared memory safely.

但是在线程之间共享内存可能会导致争用情况。 为了避免出现竞争情况,引入了“ Atomics ”全局对象。 原子提供了多种方法来在线程使用其数据时锁定共享内存。 它还提供了安全地更新该共享内存中此类数据的方法。

The recommendation is to use this feature via some library, but right now there are no libraries built on top of this feature.
建议通过一些库使用此功能,但是目前在此功能之上没有库。

If you are interested, I recommend reading:

如果您有兴趣,我建议阅读:

  1. From Workers to Shared Memory — lucasfcosta

    从工人到共享记忆 -lucasfcosta

  2. A cartoon intro to SharedArrayBuffersLin Clark

    SharedArrayBuffers的卡通简介 Lin Clark

  3. Shared memory and atomicsDr. Axel Rauschmayer

    共享内存和原子 Axel Rauschmayer博士

2.删除了标记模板字面量限制 (2. Tagged Template literal restriction removed)

First, we need to clarify what a “Tagged Template literal” is so we can understand this feature better.

首先,我们需要弄清楚“标记模板文字”是什么,以便我们可以更好地理解此功能。

In ES2015+, there is a feature called a tagged template literal that allows developers to customize how strings are interpolated. For example, in the standard way strings are interpolated like below…

在ES2015 +中,有一个称为标记模板文字的功能,该功能允许开发人员自定义字符串的内插方式。 例如,以标准方式插入字符串,如下所示……

In the tagged literal, you can write a function to receive the hardcoded parts of the string literal, for example [ ‘Hello ‘, ‘!’ ] , and the replacement variables, for example,[ 'Raja'] , as parameters into a custom function (for example greet ), and return whatever you want from that custom function.

在带标记的文字中,您可以编写一个函数来接收字符串文字的硬编码部分,例如[ 'Hello ', '!' ] [ 'Hello ', '!' ]和替换变量(例如[ 'Raja'] )作为自定义函数的参数(例如greet ),然后从该自定义函数返回所需的内容。

The below example shows that our custom “Tag” function greet appends time of the day like “Good Morning!” “Good afternoon,” and so on depending on the time of the day to the string literal and returns a custom string.

下面的示例显示了我们自定义的“标记”功能greet像“早安!”那样添加一天中的时间。 “下午好”,依此类推,取决于一天中的时间,返回字符串文字并返回自定义字符串。

//A "Tag" function returns a custom string literal.
//In this example, greet calls timeGreet() to append Good //Morning/Afternoon/Evening depending on the time of the day.

function greet(hardCodedPartsArray, ...replacementPartsArray) {
 console.log(hardCodedPartsArray); //[ 'Hello ', '!' ]
 console.log(replacementPartsArray); //[ 'Raja' ]
    
let str = '';
 hardCodedPartsArray.forEach((string, i) => {
  if (i < replacementPartsArray.length) {
   str += `${string} ${replacementPartsArray[i] || ''}`;
  } else {
   str += `${string} ${timeGreet()}`; //<-- append Good morning/afternoon/evening here
  }
 });
 return str;
}

//🚀Usage:
const firstName = 'Raja';
const greetings = greet`Hello ${firstName}!`; //👈🏼<-- Tagged literal

console.log(greetings); //'Hello  Raja! Good Morning!' 🔥

function timeGreet() {
 const hr = new Date().getHours();
 return hr < 12
  ? 'Good Morning!'
  : hr < 18 ? 'Good Afternoon!' : 'Good Evening!';
}

Now that we discussed what “Tagged” functions are, many people want to use this feature in different domains, like in Terminal for commands and HTTP requests for composing URIs, and so on.

现在,我们讨论了什么是“标记”功能,许多人希望在不同的域中使用此功能,例如在Terminal中用于命令和用于编写URI的HTTP请求,等等。

⚠️标签字符串文字的问题 (⚠️The problem with Tagged String literal)

The problem is that ES2015 and ES2016 specs doesn’t allow using escape characters like “\u” (unicode), “\x”(hexadecimal) unless they look exactly like `\u00A9` or \u{2F804} or \xA9.

问题在于,ES2015和ES2016规范不允许使用转义字符,例如“ \ u”(unicode),“ \ x”(十六进制),除非它们看起来与“ \ u00A9”或\ u {2F804}或\ xA9完全一样。

So if you have a Tagged function that internally uses some other domain’s rules (like Terminal’s rules), that may need to use \ubla123abla that doesn’t look like \u0049 or \u{@F804}, then you would get a syntax error.

所以,如果你有一个标记功能在内部使用一些其他领域的规则(如终端的规则),可能需要使用\ ubla123abla并不像\ u0049或\∪{@ F804},然后你会得到一个语法错误。

In ES2018, the rules are relaxed to allow such seemingly invalid escape characters as long as the Tagged function returns the values in an object with a “cooked” property (where invalid characters are “undefined”), and then a “raw” property (with whatever you want).

在ES2018中,放宽了规则以允许使用看似无效的转义字符,只要Tagged函数返回对象中具有``cooked''属性(其中无效字符为``undefined'')和``raw''属性(与您想要的任何东西)。

function myTagFunc(str) { 
 return { "cooked": "undefined", "raw": str.raw[0] }
} 

var str = myTagFunc `hi \ubla123abla`; //call myTagFunc

str // { cooked: "undefined", raw: "hi \\unicode" }

3.正则表达式的“ dotall”标志 (3. “dotall” flag for Regular expression)

Currently in RegEx, although the dot(“.”) is supposed to match a single character, it doesn’t match new line characters like \n \r \f etc.

当前在RegEx中,尽管点(“。”)应该匹配单个字符,但不匹配\n \r \f etc换行符。

For example:

例如:

//Before
/first.second/.test('first\nsecond'); //false

This enhancement makes it possible for the dot operator to match any single character. In order to ensure this doesn’t break anything, we need to use \s flag when we create the RegEx for this to work.

此增强功能使点运算符可以匹配任何单个字符。 为了确保它不会破坏任何内容,我们在创建RegEx时需要使用\s标志来使其正常工作。

//ECMAScript 2018
/first.second/s.test('first\nsecond'); //true   Notice: /s ??

Here is the overall API from the proposal doc:

这是提案文档中的总体API:

4. RegExp命名组捕获? (4. RegExp Named Group Captures ?)

This enhancement brings a useful RegExp feature from other languages like Python, Java and so on called “Named Groups.” This features allows developers writing RegExp to provide names (identifiers) in the format(?<name>...) for different parts of the group in the RegExp. They can then use that name to grab whichever group they need with ease.

此增强功能带来了其他语言(如Python,Java等)的有用的RegExp功能,称为“命名组”。 此功能允许开发人员编写RegExp,以便为RegExp中组的不同部分提供格式为(?<name>...)名称(标识符)。 然后,他们可以使用该名称轻松地获取所需的任何组。

4.1基本命名组示例 (4.1 Basic Named group example)

In the below example, we are using (?<year>) (?<month>) and (?<day>) names to group different parts of the date RegEx. The resulting object will now contain a groups property with properties year, month , and day with corresponding values.

在下面的示例中,我们使用(?<year>) (?<month>) and (?<day>)名称对日期RegEx的不同部分进行分组。 现在,结果对象将包含一个groups属性,其属性为yearmonthday ,并具有相应的值。

4.2在正则表达式本身中使用命名组 (4.2 Using Named groups inside regex itself)

We can use the \k<group name> format to back reference the group within the regex itself. The following example shows how it works.

我们可以使用\k<group name>格式在正则表达式本身中向后引用该组。 以下示例显示了它的工作方式。

4.3在String.prototype.replace中使用命名组 (4.3 Using named groups in String.prototype.replace)

The named group feature is now baked into String’s replace instance method. So we can easily swap words in the string.

现在,已命名的组功能包含在String的replace实例方法中。 因此,我们可以轻松地在字符串中交换单词。

For example, change “firstName, lastName” to “lastName, firstName”.

例如,将“ firstName,lastName”更改为“ lastName,firstName”。

5.对象的其余属性 (5. Rest properties for Objects)

Rest operator ... (three dots) allows us to extract Object properties that are not already extracted.

Rest运算符... (三个点)使我们能够提取尚未提取的对象属性。

5.1您可以使用rest帮助仅提取所需的属性 (5.1 You can use rest to help extract only properties you want)
5.2甚至可以删除不需要的物品! ?? (5.2 Even better, you can remove unwanted items! ??)

6.传播对象的属性 (6. Spread properties for Objects)

Spread properties also look just like rest properties with three dots ... but the difference is that you use spread to create (restructure) new objects.

传播属性也看起来像带有三个点的其余属性...但是区别在于您使用传播来创建(重组)新对象。

Tip: the spread operator is used in the right side of the equals sign. The rest are used in the left-side of the equals sign.

提示:等号的右侧使用了扩散算子。 其余的用于等号的左侧。

7. RegExp后置断言 (7. RegExp Lookbehind Assertions)

This is an enhancement to the RegEx that allows us to ensure some string exists immediately *before* some other string.

这是对RegEx的增强,它使我们能够确保某些字符串其他字符串之前*之前存在。

You can now use a group (?<=…) (question mark, less than, equals) to look behind for positive assertion.

现在,您可以使用组(?<=…) (问号,小于等于)来向后寻找肯定的断言。

Further, you can use (?<!…) (question mark, less than, exclamation), to look behind for a negative assertion. Essentially this will match as long as the -ve assertion passes.

此外,您可以使用(?<!…) (问号,小于,感叹号)来查找否定断言。 本质上,只要-ve断言通过,这将匹配。

Positive Assertion: Let’s say we want to ensure that the # sign exists before the word winning (that is: #winning) and want the regex to return just the string “winning”. Here is how you’d write it.

正断言:我们要确保我们说#签个字之前存在winning :(即#winning并希望正则表达式来仅返回字符串“中奖”)。 这是您的编写方式。

Negative Assertion: Let’s say we want to extract numbers from lines that have € signs and not $ signs before those numbers.

否定断言:假设我们要从在这些数字前带有€符号而不是$符号的行中提取数字。

8. RegExp Unicode属性转义 (8. RegExp Unicode Property Escapes)

It was not easy to write RegEx to match various unicode characters. Things like \w , \W , \d etc only match English characters and numbers. But what about numbers in other languages like Hindi, Greek, and so on?

编写RegEx以匹配各种unicode字符并不容易。 \w\W\d等仅匹配英文字符和数字。 但是其他语言(如印地语,希腊语等)中的数字呢?

That’s where Unicode Property Escapes come in. It turns out Unicode adds metadata properties for each symbol (character) and uses it to group or characterize various symbols.

这就是Unicode Property Escapes出现的地方。 事实证明Unicode为每个符号(字符)添加了元数据属性,并使用它来对各种符号进行分组或表征。

For example, Unicode database groups all Hindi characters(हिन्दी) under a property called Script with value Devanagari and another property called Script_Extensions with the same value Devanagari. So we can search for Script=Devanagari and get all Hindi characters.

例如,Unicode数据库将所有印地语字符(हिन्दी)分组为一个名为Script的属性,其值为Devanagari ,另一个属性名为Script_Extensions ,其属性为Devanagari 。 因此,我们可以搜索Script=Devanagari并获取所有印地语字符。

Devanagari can be used for various Indian languages like Marathi, Hindi, Sanskrit, and so on.

梵文可以用于各种印度语言,例如马拉地语,北印度语,梵语等。

Starting in ECMAScript 2018, we can use \p to escape characters along with {Script=Devanagari} to match all those Indian characters. That is, we can use: \p{Script=Devanagari} in the RegEx to match all Devanagari characters.

从ECMAScript 2018开始,我们可以使用\p转义字符以及{Script=Devanagari}以匹配所有这些印度字符。 也就是说,我们可以 在RegEx中 使用 \p{Script=Devanagari} 来匹配所有梵文字符。

//The following matches multiple hindi character
/^\p{Script=Devanagari}+$/u.test('हिन्दी'); //true  
//PS:there are 3 hindi characters h

Similarly, Unicode database groups all Greek characters under Script_Extensions (and Script ) property with the value Greek . So we can search for all Greek characters using Script_Extensions=Greek or Script=Greek .

类似地,Unicode数据库将Script_Extensions (和Script )属性下的所有希腊字符Script_Extensions为值Greek 。 因此,我们可以使用Script_Extensions=GreekScript=Greek搜索所有希腊字符。

That is, we can use: \p{Script=Greek} in the RegEx to match all Greek characters.

也就是说,我们可以 在RegEx中 使用 \p{Script=Greek} 来匹配所有希腊字符。

//The following matches a single Greek character
/\p{Script_Extensions=Greek}/u.test('π'); // true

Further, the Unicode database stores various types of Emojis under the boolean properties Emoji, Emoji_Component, Emoji_Presentation, Emoji_Modifier, and Emoji_Modifier_Base with property values as `true`. So we can search for all Emojis by simply selecting Emoji to be true.

此外,Unicode数据库在布尔属性EmojiEmoji_ComponentEmoji_PresentationEmoji_ModifierEmoji_Modifier_Base的布尔属性下存储各种类型的Emoji ,其属性值为“ Emoji_Modifier_Base ”。 因此,我们只需选择正确的Emoji即可搜索所有Emoji

That is, we can use: \p{Emoji} ,\Emoji_Modifier and so on to match various kinds of Emojis.

也就是说,我们可以使用: \p{Emoji} \Emoji_Modifier 等来匹配各种 \p{Emoji}

The following example will make it all clear.

下面的示例将使一切变得清楚。

//The following matches an Emoji character
/\p{Emoji}/u.test('❤️'); //true

//The following fails because yellow emojis don't need/have Emoji_Modifier!
/\p{Emoji}\p{Emoji_Modifier}/u.test('✌️'); //false

//The following matches an emoji character\p{Emoji} followed by \p{Emoji_Modifier}
/\p{Emoji}\p{Emoji_Modifier}/u.test('✌🏽'); //true

//Explaination:
//By default the victory emoji is yellow color.
//If we use a brown, black or other variations of the same emoji, they are considered
//as variations of the original Emoji and are represented using two unicode characters.
//One for the original emoji, followed by another unicode character for the color.
//
//So in the below example, although we only see a single brown victory emoji,
//it actually uses two unicode characters, one for the emoji and another
// for the brown color.
//
//In Unicode database, these colors have Emoji_Modifier property.
//So we need to use both \p{Emoji} and \p{Emoji_Modifier} to properly and
//completely match the brown emoji.
/\p{Emoji}\p{Emoji_Modifier}/u.test('✌🏽'); //true

Lastly, we can use capital "P”(\P ) escape character instead of small p (\p ), to negate the matches.

最后,我们可以使用大写的“ P”( \P )转义字符代替小p( \p ) 来否定匹配项。

References:

参考文献:

  1. ECMAScript 2018 Proposal

    ECMAScript 2018提案

  2. https://mathiasbynens.be/notes/es-unicode-property-escapes

    https://mathiasbynens.be/notes/es-unicode-property-escapes

8. Promise.prototype.finally() (8. Promise.prototype.finally())

finally() is a new instance method that was added to Promise. The main idea is to allow running a callback after either resolve or reject to help clean things up. The finally callback is called without any value and is always executed no matter what.

finally()是已添加到Promise中的新实例方法。 主要思想是允许在resolvereject之后运行回调,以帮助清理问题。 finally 回调将被调用而没有任何值,并且无论如何始终执行。

Let’s look at various cases.

让我们看看各种情况。

9.异步迭代 (9. Asynchronous Iteration)

This is an *extremely* useful feature. Basically it allows us to create loops of async code with ease!

这是*非常有用的功能。 基本上,它使我们可以轻松地创建异步代码循环!

This feature adds a new “for-await-of” loop that allows us to call async functions that return promises (or Arrays with a bunch of promises) in a loop. The cool thing is that the loop waits for each Promise to resolve before doing to the next loop.

此功能添加了一个新的“ for-await-of”循环,该循环允许我们调用异步函数,该函数在循环中返回promise(或带有promise的Arrays)。 很棒的事情是,循环在执行下一个循环之前等待每个Promise解决。

That’s pretty much it!

差不多了!

If this was useful, please click the clap 👏 button down below a few times to show your support! ⬇⬇⬇ 🙏🏼

如果这样做有用,请几次单击下面的拍手👏按钮以表示支持! 🙏🏼

https://medium.com/@rajaraodv/latest

https://medium.com/@rajaraodv/latest

  1. Check out these useful ECMAScript 2015 (ES6) tips and tricks

    查看这些有用的ECMAScript 2015(ES6)提示和技巧

  2. 5 JavaScript “Bad” Parts That Are Fixed In ES6

    ES6中修复的5个JavaScript“不良”部分

  3. Is “Class” In ES6 The New “Bad” Part?

    ES6中的“类”是新的“不良”部分吗?

翻译自: https://www.freecodecamp.org/news/here-are-examples-of-everything-new-in-ecmascript-2016-2017-and-2018-d52fa3b5a70e/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值