文章并非通篇翻译,而是进行了摘要,有兴趣的小伙伴建议直接阅读原文,有什么好的建议,或者不对的地方,欢迎留言或者@我
原文链接:medium.freecodecamp.org/here-are-ex…
下文包含了18个 TC39 已完成提案的特性
- ECMAScript 2016
- ECMAScript 2017
- 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))
字符串填充(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
- A cartoon intro to SharedArrayBuffers — Lin Clark
- Shared memory and atomics — Dr. Axel Rauschmayer
模板字符串限制被移除(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)
如题,更多内容可以点击查看
//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 ...