文章并非通篇翻译, 而是进行了摘要, 有兴趣的小伙伴建议直接阅读原文, 有什么好的建议, 或者不对的地方, 欢迎留言或者 @我
下文包含了 18 个 TC39 已完成提案的特性
- ECMAScript 2016
- Array.prototype.includes
幂中缀运算符(Exponentiation infix operator)
- ECMAScript 2017
- Object.values()
- Object.entries()
字符串填充(String padding)
Object.getOwnPropertyDescriptors
函数参数后面加逗号(Add trailing commas in the function parameters)
- Async/Await
- ECMAScript 2018
共享内存和 atomics (shared memory and atomics)
模板字符串限制被移除(Tagged Template literal restriction removed)
正则表达式的 "dotall" 符号("dotall" flag for Regular exporession)
正则表达式的命名分组捕获(RegExp Named Group Captures)
- Rest properties for Objects
- Spread properties for Objects
正则表达式的回溯断言(RegExp Lookbehind Assertions)
正则表达式的 Unicode 转义字符(RegExp Unicode Property Escapes)
Promise.prototype.finally()
异步迭代(Asynchronous Iteration)
- ECMAScript 2016
- Array.prototype.includes
数组的 includes 方法可以非常简单的判断谋项是否存在于数组中, 包括 NaN
- const arr = [1, 2, 3, 4, NaN]
- // 使用 indexOf 的情况
- if (arr.indexOf(3)>= 0) {
- console.log(true)
- }
- // 使用 includes
- if (arr.includes(3)) {
- console.log(true)
- }
- // PS: indexOf 无法搜索 NaN
- arr.includes(NaN) // true
- arr.indexOf(NaN) // -1
幂中缀运算符(Exponentiation infix operator)
类似 ++ --, 使用 ** 可以快速进行幂运算
- // 使用 Math.pow
- Math.pow(7, 2) // 49
- // 使用 **
- 7**2 // 49
- ECMAScript 2017
- Object.values()
可以用于获取 Object 的值, 类似 Object.keys() 用于获取 Object 中的 key
- const cars = { BMW: 3, Tesla: 2, Toyota: 1 }
- // 使用 Object.keys() 加上 map 的方式获取值
- const vals = Object.keys(cars).map(key => cars[key])
- console.log(vals) // [3, 2, 1]
- // 使用 Object.values()
- const values = Object.values(cars)
- console.log(values) // [3, 2, 1]
- Object.entries()
将对象的 key 和 value 变为数组的形式, 便于对象的遍历或者将 Object 转换为 Map
- // 使用效果
- const cars = { BMW: 3, Tesla: 2, Toyota: 1 }
- const entries = Object.entries(cars)
- console.log(entries) // [ ['BMW', 3], ['Tesla', 2], ['Toyota', 1] ]
- // 将 Object 转化为 Map
- const cars = { BMW: 3, Tesla: 2, Toyota: 1 }
- const map1 = new Map(Object.entries(cars))
关于 Map 相关的资料点击这里 https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/0014345007434430758e3ac6e1b44b1865178e7aff9082e000
字符串填充(String padding)
可以使用
String.prototype.padStart
和
String.prototype.padEnd
来填充字符串
- // 其中第一个参数代表字符串的最终的长度, 第二个参数表示需要填充的内容
- // 从头开始填充
- '5'.padStart(10, '*') // '*********5'
- // 从尾开始填充
- '5'.padEnd(10, '*') // '5*********'
- Object.getOwnPropertyDescriptors
用于返某个 Object 的所有细节包括(get,set)
可以通过 Object 的浅拷贝 (Object.assign) 和深拷贝 (Object.defineProperties) 来验证
- var Car = {
- name: 'BMW',
- price: 1000000,
- set discount(x) {
- this.d = x;
- },
- get discount() {
- return this.d;
- }
- }
- console.log(Object.getOwnPropertyDescriptor(Car, 'discount'));
- // {
- // get: [Function: get],
- // set: [Function: set],
- // enumerable: true,
- // configurable: true
- // }
- // Object.assign
- const ElectricCar = Object.assign({}, Car)
- console.log(Object.getOwnPropertyDescriptor(ElectricCar, 'discount'))
- // {
- // value: undefined,
- // writable: true,
- // enumerable: true,
- // configurable: true
- // }
- // Object.defineProperties
- const ElectricCar2 = Object.defineProperties({}, Object.getOwnPropertyDescriptors(Car))
- console.log(Object.getOwnPropertyDescriptor(ElectricCar2, 'discount'))
- // { get: [Function: get],
- // set: [Function: set],
- // enumerable: true,
- // configurable: true
- // }
函数参数后面加逗号(Add trailing commas in the function parameters)
这样的原因是为了类似使用 git 这类的工具时, 只有新增的行发生变化(可能和代码风格有关)
Async/Await
这个应该都比较熟悉了, 直接上例子
- function getUser() {
- return new Promise(resolve => {
- setTimeout(() => {
- resolve('join')
- }, 1000)
- })
- }
- function getBankBalance() {
- return new Promise(resolve => {
- setTimeout(() => {
- resolve('$1,000')
- }, 2000)
- })
- }
- // 使用 async/await 之前
- function getAmount() {
- getUser()
- .then(getBankBalance)
- .then(amount => {
- console.log(amount)
- })
- }
- // 使用 async/await 之后
- async function getAmount2() {
- var user = await getUser()
- var amount = await getBankBalnce(user);
- console.log(amount)
- }
Async 函数自身返回的是一个 Promise 所以可以使用 .then 方法
async/await 并行使用 Promise.all
- function doulieAfterSec() {
- return new Promise(resolve => {
- setTimeout(resolve(2), 1000)
- })
- }
- async function doubleAdded() {
- [a, b] = await Promise.all(doulieAfterSec(), doulieAfterSec())
- }
- ECMAScript 2018
共享内存和 atomics (shared memory and atomics)
一个比较高级的特性, 还是自行查看作者给出的文章吧
From Workers to Shared Memory-lucasfcosta http://lucasfcosta.com/2017/04/30/JavaScript-From-Workers-to-Shared-Memory.html
A cartoon intro to SharedArrayBuffers-Lin Clark https://medium.com/@linclark
Shared memory and atomics-Dr. Axel Rauschmayer http://2ality.com/2017/01/shared-array-buffer.html
模板字符串限制被移除(Tagged Template literal restriction removed)
在 ES2016 和 ES2016 规范中, 模板字符串不允许使用的转义字符, 类似 \ u,\x
但是在 ES2018, 放宽了这个要求, 允许出现这些字符串, 你可以定义一个 Object, 里面有 cooked 这个属性(也可以是任意一个属性), 来表示 "undefined", 然后再定义一个 raw 属性(也可以是任意你想要的名字), 将这些 \u,\x 字符存储在 raw 中
- function myTagFunc(str) {
- console.log(str) // [undefined, raw: [['hi \ubla123abla']]]
- return { "cooked": "undefined", "raw": str.raw[0] }
- }
- var str = myTagFunc `hi \ubla123abla`
- str // { cooked: "undefined", raw: "hi \ubla123abla" }
正则表达式的 "dotall" 符号("dotall" flag for Regular exporession)
在正则表达式中,. 符号允许匹配任意字符, 但是不匹配换行字符, 类似 \n`\r\f
等
但是在 ES2018 中, 增加了
/first.second/s 中的 / s 标志位来表示.` 来支持匹配换行字符
- // 在不支持之前
- /first.second/.test('first\nsecond'); //false
- // 在 ES2018 中
- /first.second/s.test('first\nsecond'); //true
正则表达式的命名分组捕获(RegExp Named Group Captures)
提供了类似 Python,Java 等语言中的命名分组(当年用 Python 写爬虫的时候相当好用), 语法格式为 (?<name>...)
- // 原先的命名分组
- let re1 = /(\d{4})-(\d{2})-(\d{2})/
- let result1 = re1.exec('2015-01-02')
- console.log(result1) // ['2015-01-02', '2015', '01', '02', index: 0, input: '2015-01-02', groups: undefined]
- // 使用命名分组后
- let re2 = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
- let result2 = re2.exec('2015-01-02')
- console.log(result2) // ['2015-01-02', '2015', '01', '02', index: 0, input: '2015-01-02', groups: { year: '2015', month: '01', day: '02'}]
- console.log(result2.groups.year) // 2015
可以使用 \k<group name> 在同一个表达式中表示相同分组
- let sameWords = /(?<fruit>apple|orange)==\k<fruit>/u;
- sameWords.test('apple==apple') // true
- sameWords.test('apple==orange') // false
字符串中的命名分组使用
- // 将 "firstName lastName" 替换为 "lastName, firstName"
- let re = /(?<firstName>[A-Za-z]+) (?<lastName>[A-Za-z]+$)/u
- 'Raja Rao'.replace(re, '$<lastName>, $<firstName>') // "Rao, Raja"
- Rest properties for Objects
使用 ... 操作符可以将 Object 的剩余未指定的属性进行赋值
- let { firstName, age, ...remaining } = {
- firstName: 'john',
- lasttName: 'smith',
- age: 20,
- height: '5.10',
- race: 'martian'
- }
- firstName // john
- age // 20
- remaining // { lasttName: 'smith', age: 20, height: '5.10', race: 'martian' }
可以用来移除不想要的项
- let { firstName, age, ...cleanObj } = {
- firstName: 'john',
- lasttName: 'smith',
- age: 20,
- height: '5.10',
- race: 'martian'
- }
- // cleanObj 就是你真正想要的属性
- cleanObj // { lasttName: 'smith', age: 20, height: '5.10', race: 'martian' }
- Spread properties for Objects
... 也可用于合并旧对象创建新对象
- const person = { fName: 'john' }
- const account = { amount: '$1000' }
- const personAndAccount = { ...person, ...account }
- personAndAccount // { fName: 'john', amount: '$1000' }
正则表达式的回溯断言(RegExp Lookbehind Assertions)
可以 (?<=...) 获取以某个特定标识之后的内容,(?<!...)获取非某个特定标识之后的内容
- '#winning'.match(/(?<=#).*/)[0] // 'winning'
- 'A gallon of milk is $3.00'.match(/(?<!\$).*/) // null
正则表达式的 Unicode 转义字符(RegExp Unicode Property Escapes)
如题, 更多内容可以点击查看 https://mathiasbynens.be/notes/es-unicode-property-escapes
- //The following matches multiple hindi character
- /^\p{Script=Devanagari}+$/u.test(''); //true
- //PS:there are 3 hindi characters h
- //The following matches a single Greek character
- /\p{Script_Extensions=Greek}/u.test('π'); // true
- Promise.prototype.finally()
Promise 增加了一个 finally() 方法, 顾名思义, 不管是 reslove 还是 reject, 最终都会执行
- let myPromise = new Promise((resolve, reject) => {
- throw new Error('wrong')
- })
- .then(val => {
- console.log(val)
- })
- .catch(e => {
- throw new Error('wrong')
- })
- .finally(() => {
- console.log('这里始终会被执行')
- })
异步迭代(Asynchronous Iteration)
顾名思义, 一个支持包含异步的迭代 for-await-of
- const promises = [
- new Promise(resolve => resolve(1)),
- new Promise(resolve => resolve(2)),
- new Promise(resolve => resolve(3))
- ]
- // 不支持的情况
- async function test1() {
- for (const obj of promises) {
- console.log(obj) // 显示 3 个 Promise 对象
- }
- }
- // 使用 for-await-of
- async function test2() {
- for await(const obj of promises) {
- console.log(obj) // 显示 1,2,3
- }
- }
- test1() // Promise, Promise, Promise
- test2()// 1, 2, 3 ...
来源: https://juejin.im/entry/5b076a0b6fb9a07aa43c9fba