ES10难吗?你只需要10分钟

4,343 阅读6分钟

写在前面的话

2019年6月4日,ES10正式draft已对外发布了。浏览器因版本的不同对Javascript标准会有兼容性问题,JavaScript的新的方法都不能使用。等到你能大批量使用的时候,版本早就迭代更多的很多新方法新属性了。那么如何保持队形,不掉队,能在stag3 or stag 4阶段的时候就推进新方法在前端应用呢? 不用担心,笔者已替你们整理踩好坑,花个10分钟来看一下,你就可以在前端玩转ES10了!!

JS标准的制定–TC39和ECMA

Every year, a new version of ECMAScript is released with the proposals which are officially ready. This means, that the proposals which have been accepted and reached stage 4 by the TC39 committee would be included in the specification of that year (assuming it hasn’t been published), and the others - are postponed to the next year.

简单来说,每一年,官方就会发布一次新的ECMAScript(以下简称ES)规范提案。也就是说,那些被TC39采纳并通过Stage 4的提案将会出现在当年正式发布的ES规范中,处于其他Stage的提案可能就会被废弃或者推迟到下一年了。

TC39是什么?

TC39是一个推动Javascript发展的委员会,由各个主流浏览器厂商的代表构成。从制定标准到落地是一个漫长的过程,而TC39就是制定ES标准、标准生成的流程,并实现。

TC39制定标准的流程是什么?

TC39的提案流程:tc39.es/process-doc…       


                                         The stages of TC39 process


如何追踪最新标准的提案进度?

查看最新提案流程进度的github地址: github.com/tc39/propos…


通过Stage 4,且被包括在ES10的提案

总览

IndexProposalsExpected Published Year
1Optional catch binding2019
2JSON superset2019
3Symbol.prototype.description2019
4Function.prototype.toString revision2019
5Object.fromEntries2019
6Well-formed JSON.stringify2019
7String.prototype.{trimStart,trimEnd}2019
8Array.prototype.{flat,flatMap}2019

详细解说

1. Optional catch binding

ES10之前,try{}catch语法中会强制默认绑定异常变量,ES10提案中,可省略掉此变量。


2. JSON superset

ES10之前,U+2028(行分隔符)和U+2029(段分隔符)都会导致ECMA字符串解析的终止,导致使用时会带来SyntaxError异常。ES10提案中,ECMA可支持识别了。


3.Symbol.prototype.description

访问Symbol描述,ES10之前,唯一方法是将符号转换成字符串,ES10提案中提供了getter Symbol.prototype.description来直接访问"Symbol description": 


MDN上的浏览器兼容信息:


4.Function.prototype.toStringrevision  现在返回更精确,包括空格、注释



5.Object.fromEntries

Object.fromEntries() 函数传入一个键值对的列表,并返回一个带有这些键值对的新对象。是Object​.entries()的反转。


MDN上的浏览器兼容信息:


6.Well-formed JSON.stringify

如果输入 Unicode 格式但是超出范围的字符,原先会直接返回格式错误的字符串,ES10会输出转义序列,并以UTF-8表示:


7.String.prototype.{trimStart,trimEnd}

trimStart 去除字符串的开头的空白部分, trimEnd 去除字符串的尾部的空白部分:


MDN上的浏览器兼容信息:

8.Array.prototype.{flat,flatMap}

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 和 深度值1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。


MDN上的浏览器兼容信息:


现阶段,各大工具对ES10的支持性

提案通过,距离发布乃至市场上的各大工具支持都还有一段很长的时间要走。。。(很多浏览器的高版本已经支持了,可参考上节的详细解说里的浏览器兼容性)

Node.js

不同版本对ES2015, ES2016, ES2017, ES2018, ES2019支持程度: node.green/

对于 Object.fromEntries,string trimming, Array.prototype.{flat, flatMap},node.js V12.1.0及以上是100%支持。

Babel

Babel,是目前业内比较优秀的ES 语法转换器。从6开始建议使用 babel-preset-env 这个能根据环境进行自动配置的预设。到了 babel7(2019-03-19发布的最新版本是v7.4.0),我们就可以完全告别这几个历史预设了: preset-es2015/es2016/es2017/latest,子模块都迁移到了@babel下,如这里的babel-preset-env 变成 @babel/preset-env。 @babel/preset-env目前最大支持是es2017的转化,明年预计发布es2018。

现在如何在前端兼容使用ES10呢?

Babel

这里不得不提到的一个概念是babel-polyfill。

Babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。

举例来说,ES6在Array对象上新增了Array.from方法。Babel就不会转码这个方法。如果想让这个方法运行,必须使用babel-polyfill,为当前环境提供一个垫片。

在Babel7以后,由于修改了命名空间为@babel, 所以需要引入的是@babel/polyfill,Babel 6及以下还是使用babel-polyfill即可(因为babel-polyfill实际上是包含了regenerator runtime and core-js的模块,混乱使用会造成polyfill会找不到core-js模块的位置)

具体修复步骤参考如下:

Step 1: 执行 npm install @babel/polyfill --save (由于需要运行在你所有source code之前,所以需要安装在dependency而不是devDependency)

Step 2: 如果你是用webpack构建的前端项目,只需在webpack.config.js的entry添加 ‘@babel/polyfill’

Note: @babel/polyfill 默认只会包含 Stage 4的提案部分,如果你需要其他stage的提案(或者当前版本的polyfill还没同步stage4的所有最新提案),需要额外引入 core-js。

Demo参考链接:github.com/JeanZhao/ES…

PS: 感兴趣的同学可以移步这里查看怎么升级Babel7: babeljs.io/docs/en/v7-…


lodash

如果你不想升级babel或引入额外的babel库件,不妨试试lodash。对于array、number、objects、string等等,除了babel,还有一种工具也可以通过降低它们的使用难度让 JavaScript 变得更简单,从而达到解决ES10里的兼容问题。

如 lodash 提供了_flatten()来处理ES10里stag-4的flat。同样可以解决这个问题。

具体修复步骤参考如下:

Step 1: 执行 npm install lodash --save

Step 2: 在使用的地方 import _ from 'lodash'; 然后就可按照如Demo里使用的lodash是4.17.11版本,官网使用教程 来查看。

Demo参考链接:github.com/JeanZhao/ES…

简易修改

如果你的项目非常原始(可能历史比较悠久,项目比较庞大),没有使用babel, lodash, 或者线上环境比较严格,也不允许你更新以上的任何第三方库件。这里还有一种解救方案。

读源码!读源码!读源码!

重要的事情说三遍!

比如flat, 本质上来说,就是递归加数组拼接(reduce+concat),你可以根据你的需求来自定义 flatten函数的逻辑:


好了,以上就是这次的分享了,欢迎大家批评指正!谢谢~