YIXUNFE / blog

文章区
151 stars 25 forks source link

ECMAScript 相关知识略述 #83

Open ajccom opened 6 years ago

ajccom commented 6 years ago

ECMAScript 相关知识略述

前言:Javascript 是一门灵活的编程语言,吸引着全世界的程序员为其构建整个生态,在 Github 语言使用榜单上,JS 一直是名列前茅。如此热门的一门语言,它自身的演化又是如何的呢?今天我们就来聊一聊,JS 的演进之路。我们会聊到 JS 与 ES 的关系,ES 规范、规范的制订过程等。最后,希望大家能够通过本篇文章了解到 ECMAScript 的一些知识。

ECMAScript 与 Javascript

ECMAScript 与 Javascript 是什么关系?这个可能是很多非前端行业的人都很好奇的一个问题,这里我们先来解答一下。

首先我们要了解到的是,ECMAScript 它是一套语言规范,即 ECMA-262 规范,制订该规范的组织叫 TC39。 它和 Javascript 的关系,通俗的讲,ECMAScript 就好像是自行车的基础构造,而 Javascript 则是使用了该基础构造的一个品牌产品,好比摩拜和 ofo,本质都是自行车,都是用了自行车的构造,有两个轮子,脚踏板,链子,刹车,龙头等,但是他们品牌不同,附加的装备也不同,比如车锁、车铃等。语言界和 Javascript 使用同样规范的有 ActionScript、JScript 和现在非常火的 NodeJS 等。

Javascript 除了 ECMAScript 提供的语法、API 和关键字等之外,还包括了宿主环境提供的 DOM 和 BOM,诸如 window 对象、XMLHttpRequest 对象、navigator 对象等。

这里也解答了一个问题,当你需要查看 DOM\BOM 相关的 API 时,不应翻 ECMA 262 规范,最好是去浏览器的官网上找 API 说明。

ECMAScript 的版本

谈到 ES 的版本,可能很多人都知道 ES 6 发布了,改名叫做 ES 2015。今年是 ES 2017 版本发布,在今年 6 月份。那么,ES 的版本是如何迭代的?版本号为何要改成年份呢?带着这两个问题,我们一起往下看。

首先,之前的名称如 ES5,这里的 5 代表的是 ECMA 262 规范的修订版本号,可以理解为第 5 版。即使现在都叫做 ES 201X,我们还是可以以这个数字作为版本号继续使用,ES 7、ES 8、ES 9...ES N。

接下来我们看下 ES 规范各个版本的发布时间:

版本 时间 间隔(年)
ES 1 1997 0
ES 2 1998 1
ES 3 1999 1
ES 4 - -
ES 5 2009 10
ES 6 2015 6
ES 7 2016 1
ES 8 2017 1

这个表格上我们看到,ES3 到 ES5 之间间隔了 10年,而且有一个版本难产而死,并没有正式发布,那就是 ES4。这是为什么呢? 这是因为,在那个 10 年之初,IE6 作为浏览器王者,一统天下,之后的 IE7,IE8 都没有带来 IE6 如此的辉煌成就。IE6 当时的盛行,导致了浏览器演进趋于停止,这也就导致浏览器使用的脚本引擎一直停滞,即使开发新的规范,没有浏览器厂商的支持,就形同于一纸空文。ES4 当时希望能解决语言方面的诸多问题,class、namespace、package 等等。但是既没有大厂支持也没有社区的支持(写 JS 的同学大多数觉得这么搞太复杂太不“灵活”),这就最终导致 ES4 规范被取消(其中也有一些不和谐的政治因素)。

时间推移,在 Chrome 诞生后,采用了新的解析引擎 V8 ,成功瓜分了浏览器市场份额,浏览器大战终于再次打响(第一次是网景和微软之间,微软完胜)。各浏览器厂商为了争取更多的用户和开发者,开始争相实现新规范,进行性能竞赛。FireFox、Chrome、Safari 等也都出了各自的新特性实施版本,如果你是开发者,可以下载这些版本体验下最新的提案内容(文章最后有链接)。

09 年诞生的 ES5,其实只是 ES3.1 版本,当初 ES 4 在推进过程中停滞不前,微软和 Yahoo 的代表就干脆另起了一份 ES3.1 规范。规范内容相较 ES4 是相对保守的。

09 年之后,到 15 年,ES6 终于面世了,这其中隔了 6 年时间主要是因为 ES6 增加了很多新功能和新语法。ES6 可以称得上是一次大的版本迭代。这其实是有风险的,委员会成员也各自表达了对这种大版本迭代形式的担忧,大家都不希望再次看到一个 “ES4 事件” 出现。所以以后的 ES 规范会每年一版,并且改名以年份作为版本号。ES6 改名叫 ES 2015,以后每年的版本依次类推。迭代的内容则是将当年 1 月份进入 Stage 4 的提案 Merge 到规范中作为当年版本的新规范。如果一个提案在当年 1 月份还没进入 Satge 4,那么就后延至下一年的版本。

目前来看,每年一个版本增加的内容并不多,ES7 仅增加了几个新内容,ES8 增加了比较重要 async await 函数。对于开发者来说,学习成本还是很低的,比学习某些框架的成本低多了。

ES 规范与提案阶段

每个规范在成为规范之前,都是委员会里的一个提案。每个提案都需要走一个处理流程,称为 TC39 process。流程共分 Stage 0 到 Stage 4,5 个阶段。最终进入 Satge 4 的提案即会成为下一个版本的规范。

我们这里看下 Satge 0 到 Stage 4 阶段都代表什么:

Stage 0: strawman

自由形式提案,表述提案包含的 ECMAScript 演变思路,由 TC39 成员(member)或已注册成为 TC39 贡献者(contributor)的非会员提交。再由 TC39 会议审查后,将提案添加到 Satge 0 阶段。

Stage 1: proposal

正式提案,此时需要为提案指定一名 TC39 成员作为提案的带头人(champion)或联合带头人(co-champion)。进入第一阶段的提案要满足:

接下来,TC39 通过接受第一阶段的建议,声明其愿意审议,讨论并对该提案作出贡献。之后,预计将对该提案进行重大修改。

Stage 2: draft

这是提案作为规范的第一个版本,与最终规范中包含的特性不会有太大差别。这一阶段要求提案必须:

满足这些条件后,提案才能正式进入第二阶段。

接下来,提案只能进行增量的修改。

Stage 3: candidate

进入这一阶段的提案已经属于基本完成了的。进入这一阶段需要满足的条件有:

接下来,只能在实施及使用过程中引起的关键问题上作出变更。

Stage 4: finished

进入这一阶段标志着提案已经准备好纳入标准。在提案进入这一阶段之前,需要满足的条件有:

是不是一定要学习 ES 201X 规范?

仅就当前看来,ES 规范很大程度上会考虑旧网页兼容性,换句话说,就是你写老代码,也依旧能行。比如在 ES 7 中新增了一个数组对象的方法,本来叫做 contains,用于返回数组中是否包含参数的值,可以说是十分贴切。但是由于老牌的脚本库 mootools 下会产生报错,所以提案最后将 contains 换成了 includes。还有如 typeof null 返回的值是 object,这些奇怪的问题也依旧在最新的规范版本中。

但是,那么多人辛苦制定的规范,是真的没什么用吗?那他们为何还要煞费苦心的指定新规范呢?

我们接下来看看,如果你不学习最新的规范,你会错过什么呢?

比如 ES6 的 Modules,它是静态的模块,可以提供静态分析,进而使用 Tree Sharking 技术可以起到为打包瘦身的效果。再比如使用 for of 可以直接遍历对象的值等等。

ES 8 加入了 async 和 await 规范(当然,你可能很早之前就用过了),它比 callback、Promise 或者 generator 都要让人更容易使用,也更容易读懂代码,是相当好的处理异步的方式。还有比如使用 let、const 定义变量,不会产生变量提升效果。

console.log(a); // 'undefined'
a = 1;
var a = 2;

console.log(b); // Uncaught ReferenceError: a is not defined
b = 1;
let b = 2;

还有使用 Set 数据结构可以得到无重复项的数组等等。

那么我只学习最新规范是否就可以不学习老的一套的了呢?其实要这样理解新规范,每一版本的规范,并不是将老规范的推倒重来,可能之后有一天,所有的新规范可以覆盖 ES3 中所有内容了,那么你那时就可以不用再学习 ES3 了,但是目前来看,你或多或少还是要学习一些“老”的内容。

大厂面试会不会问 ES 新规范

面试中基本上都会问新规范,但从面试技巧上讲,可能并不会那么直接的发问一些纯知识型的问题,比如:

你能告诉我一下 ES 7 中 Array 对象新增了哪些方法,又是怎么用的呢?

这种问题就比较无聊,而且容易使候选人产生一种 “我看一眼就知道了呀” 的抗拒心理。所以一般面试官会以场景出题,可能是这么问:

现在有一个巨大的数组,你有哪些方法可以告诉我,如何判断一个数字都否在该数组中?

这样问,候选人如果知道新规范的实现方法,那肯定是有加分的。

还有比如会问:

我们的 Node 项目中有特别多的异步请求,比如有一个请求需要在前置的请求完成之后发送,你能否帮我设计一下代码思路?

这个时候你会想到什么样的答案呢?

我该如何学习 ES 最新规范

如果业务工作量很大,没那么多时间的话,建议半年或者一年学习一次最新规范,可以订阅一些业界名人的博客、论坛等。如果时间比较充裕,可以通过看 TC39 的 proposals 页面,了解到委员会最新的一些提案。

https://github.com/tc39/proposals

光看了文档,也需要有实现最新提案的浏览器,可以使用厂商推出的新规范实施版本进行尝试:

firefox nightly: https://www.mozilla.org/en-US/firefox/channel/desktop/#nightly chrome canary: https://google-chrome-canary.en.softonic.com/ Safari Technology Preview: https://developer.apple.com/safari/download/

最后

前端在 09 年之后,随着 ES5、NodeJS 的出现,发生了翻天覆地的变化。我们开发工具从 DW、notepad++ 换到了 Sublime、VS Code,我们发布过程加入了基于 grunt、gulp、webpack 等的工作流,我们样式书写也从简单的配置文件到 OO 编程,而最大的变化,莫过于我们所写的 JS。从 ES3 到 ES5,再到 ES2015,至今已经是 ES2017,我们有理由相信,ES 的未来是美好的。

2016 年,JS 语言高居 Github 项目使用语言第一名。