从 JavaScript、ES6、ES7 到 ES10,你学到哪儿了?

2,510 阅读10分钟

作者:Yann s

翻译:疯狂的技术宅

原文:medium.com/engineered-…

未经允许严禁转载

img

**什么是 JavaScript?**据 Wikipedia 的描述,它是一种符合 ECMAScript 规范的脚本语言。 ES6ES7等这些名字你可能听说过,你也很可能已经使用 ES6 有一段时间了(在很多情况下通过 Babel 使用)。

我确定你们中的大多数人都在使用许多不同的 ES6 新功能,而无需问自己:这真的是 ES6吗,浏览器支持该功能吗?不过你对 Babel 在 2019 年进行的转换了解多少?你是否重新了解了 ES 中的内容?自从首次提出 ES6 提案以来,删除了哪些内容?自最初的 ES7 提案以来又增加了什么?

让我们坐下来回顾一下 ES 的当前状态。自 Babel 和 ES6 诞生以来都发生了什么,什么已完全集成?

一些历史和扫盲

我认为让你重新了解某项目的不同阶段是很有用的。

当他们这么做的时候,我真的不知道这究竟代表什么。

本质上,这些功能经历了从 0 到 4 的阶段,0 是最早的阶段,而 4 是“准备发布”。

img

阶段 0 是纯属有人提出的想法,将其整理为阶段 1 的提案,进行审查和讨论,直到阶段 3 为止,最终将其划分为阶段 4 的优先级。到达阶段 4 后,将会在浏览器中实现并计划发布。

在此处获取所有 deetstc39.es/process-doc…



ES6 和 ES7 —— 提醒

简而言之,ES6(或 ES2015)是根据 2015里程碑 通过了第4阶段的一系列功能。换句话说,如果你对 ES6 有很好的理解,并且对 ES7 有一定的了解,那么你大约有4年的时间可以追赶……没有压力。

让我们看一下 ES6 的正式组成部分。顺便说一下,所有这些功能在所有浏览器中都得到正式支持。换句话说,不管你使用哪个浏览器都不需要 Babel(除非你需要支持 IE 11)。

ES6 中,我们能够得到:

创建和继承类的能力。

class MyComponent extends React.Components {}

具有导入和导出功能的ES6模块。

import * from 'React';export default MyComponent;

生成器

let fibonacci = {     
  *[Symbol.iterator]() {         
    let pre = 0, cur = 1         
    for (;;) { 
      [ pre, cur ] = [ cur, pre + cur ]
        yield cur
    }
  }
}

我们还有:模板,箭头函数,Promise,新的数字类型,Const/Let,类型化数组,数组解构,Map/Set,符号。

这里是所有功能的列表:es6-features.org

你注意到了吗?装饰器,对象解构(例如 React props:{…props})等都不属于 ES6!

关于在 ES7(ES2016) 中,以下是我们能够得到的。这是一个很小的更新:

  • 幂运算符base ** exponent
  • 数组包含 array.includes(myItem) // true 或 false

资料来源: ecma-international.org/ecma-262/7.…

你可能已经注意到 Async/Await 不是 ES7 的一部分,而是属于 ES8!

ES8, ES9, ES10

在过去的两年中,每个接受过 JavaScript 相关面试的人都被问到过 ES6 是什么以及它带来什么功能。但是有人发现 JS 显然并没有突然停留在 ES6 和 ES7 上,但是没有人问你个吗?这是你纠正问题的机会!

在 **ES8(ES2017)**中,以下是可用功能:

  • Object.entries / Object.values(数组的值/键等效对象)
  • 字符串填充 myString.padStart(2); // 或 padEnd
  • Trailing coma function test(a,b,c, ) // notice the coma after c
  • 原子和共享内存:developer.mozilla.org/zh-CN/docs/…

当然还有 Async/Await 函数:

async MyAjaxGetCall(url) {
  return ajax.get(url)
}const response = await MyAjaxGetCall("/getUsers");
console.log(response) // response is available without using promise.then

如果你已经阅读了这篇文章,那么现在应该明白了:除少数例外,这些功能是 Stage 4,你可以在没有 Babel 的浏览器中使用它们(也就是说,ES8 是 ES2017,它仍然是最新的, Edge 和 Opera 之类的引擎对某些实现滞后了一点)。

img

现在转到 ES9。就像 ES8 和 ES6 一样,ES9(或ES2018)是一个相当重要的更新:

img

大多数浏览器已经支持这些功能!

最后,转到 ES10(或 ES2019)!

  • Array.flat: [[1,2],3]).flat() // [1,2,3]
  • Array.flatMap: 等同于 map().flat()
  • Object.fromEntries: Object.entries 的反向操作(参见此处
  • String.trimStart() 和 String.trimEnd(): 删除字符串中的多余空格
  • 可选的 Catch 绑定:无需在 catch 中添加参数(现在你可以用 } catch { 而不是 } catch(e){
  • 重新提出 Function.toString 的行为一致性的问题🥳🥳🥳
  • 符号说明
  • BigInt(64位数字)
  • 改进了对 JSON.stringify() 的 Unicode 支持
  • 如果 key 相同,则 Array.sort 保留其顺序
const array = [
 {key: 2, value: 'd'},
 {key: 1, value: 'a'},
 {key: 1, value: 'b'},
 {key: 1, value: 'c'},
];
array.sort(...)
/*
[
 {key: 1, value: 'a'},
 {key: 1, value: 'b'},
 {key: 1, value: 'c'},
 {key: 2, value: 'd'},
]
*/
  • 将 JavaScript 设为 JSON 的超集(此处有详细信息

那么 ES5 呢?

如果 ES6 是 ES2015,而 ES7 是 ES2016,你能猜出 ES5 属于哪一年吗?

…你输了! (除非你真的知道,但因为我听不到你的声音,所以我假设你错了)。 ES5 是 ES2009!

在 ES5 之前,最后一次 ES 更新是在 1999 年!

img

如你所见,从 97 到 99 更新非常频繁,在之后的 16 年里,ES5 是唯一的更新!

img

我们如何解释呢?好吧,我认为这有两个因素。

第一个是技术上的:“JavaScript 很烂”。老实说,确实如此。那时,我们有一些 JS 的替代品:Java Applets,ActiveX 甚至 Flash。

直到 2011 年之前,不仅这些技术比 JS 快好几个数量级, 而且它们还具有我们仍在为 JS 努力争取的很多功能。 (Java 具有所有的语言功能,例如类和装饰器,支持多线程,OpenGL,套接字等)。当 Chrome 和 Google 入场后并在 2013 年宣布淘汰 Java(然后是 Flash)时,JS 赶上其竞争对手的征战已经开始。两年后,我们有了ES6。

第二个因素是经济上的:2000 年是互联网泡沫爆发的一年。对于你们中最小的孩子,想像一下几年前的比特币,互联网初创公司在 90 年代后期是一样的。初创公司为了获得大量的风险投资在名称的末尾添加了 .com(就像现在的 mySuperStartup**.ai** 一样),直到其价值在 20 年代突然下降。这是一个非常基本的解释,请你看一下 wikipedia 上文章来获得更详细的解释。

关键是,Internet 不再获得使 JS 和与 Web 相关的技术成为焦点所需的吸引力。后来随着 Amazon、Facebook 和 Google 的兴起,Web 有了新的发展理由,我们选择 JS 是合乎逻辑的! Chrome 于2008 年发布,并在 2014 年成为最受欢迎的浏览器:这是 ES6 发行的第一年。

少了些什么东西? (被拒绝的提案)

这是一份从未进入第 4 阶段提案的详尽列表。你可以在此处阅读更多信息:github.com/tc39/propos…

Object.observe

最初它允许 JS 观察代码中的值:

var obj = {
  foo: 0,
  bar: 1
};

Object.observe(obj, function(changes) {
  console.log(changes);
});obj.baz = 2;
// [{name: 'baz', object: <obj>, type: 'add'}]

这是一个很棒的功能,很明显你可以通过代码(或 polyfill)来实现它,但是在浏览器中实现它的前提是实现更快的响应保证(例如:Angular 使用了大量观察者)。之所以撤销,是因为他们无法实现稳定性能。 此处有更多详细信息

可取消的 Promise

不言而喻,我敢肯定,这并不是唯一缺少的功能。这个想法允许开发人员随时取消任何 Promise 的执行。

用例会有所不同,例如,在异步操作时使客户端超时,或者,如果你有一个选项卡驱动的导航系统,并且用户在加载当前选项卡的内容之前单击了另一个选项卡。

blöcks

我之所以仅提及这一点,是因为我喜欢它的名字,也因为它是一个与 Go Routines 或 C# Tasks 类似的出色功能。

const blöck = await {|
  // This code is Async, but most importantly, executed in another thread
|};

其他

还有一些有趣的建议,例如可调用的构造函数。其中大多数要么由于原始作者的原因而被撤回,要么因为与现有计划中的特征冲突或重叠而被拒绝。


下一步是什么?

目前,阶段 0 ~ 3 中有一些令人兴奋的东西。我会强调一些:

Observables (Stage 0)

Observe 已被拒绝,但战斗并没有停止,Observable 是一项改进 API 的提案,旨在消除 Observe() 遇到的性能瓶颈。

tc39.es/proposal-ob…

String.ReplaceAll (Stage 3)

github.com/tc39/propos…

顶级 Await (Stage 3)

使用 Await 要求你处于异步函数内,这意味着你不能简单地删除包含 await 的脚本标签,这不一定有意义,并且限制了 ES6 模块在浏览器中无缝运行。它还允许你执行 fetch 操作或者不执行操作。

// You can do this in a .js file:
fetch(...).then((res) => something = res);
// But you can't do this unless you have a Async keyword
const res = await fetch(...);

github.com/tc39/propos…

可选链

也称为猫王(Elvis)运算符(我就是要这样称呼它,你无法阻止我!),可让你轻松浏览对象而不会引发错误:

const test = myObject && myObject.a;
// equivalent to
const test = myObject?.a;

之所以称为猫王(Elvis)运算符,是因为运算符 ?: 看起来像猫王的侧脸。

该提案还提到了 Nullish 合并运算符

let x = 0 || 1; // x is 1 because 0 is falsy
let x = 0 ?? 1; // Since 0 is defined, x is 0

结论和常见问题

好长!可以肯定的是,你记不住所有内容,坦白地说,我也记不住!希望本文对你有一个全面的概述,并鼓励你重新考虑对 JavaScript 的看法!我想从最常见的问题开始解答:

我仍然需要 Babel 吗?

很好的问题!考虑到 JS(ES6 至 ES9)的最常见功能,已经完全在除了 IE11 之外的浏览器中实现。你可能会认为:“那么,这还不够好”。是的,还不够好,因为你做出了选择,所以你应该考虑:

  • 在我撰写本文时,目前 IE11 的浏览器占有率为 1.86%。但是不支持 IE11 并不意味着你会失去 1.86% 的受众群体,因为你应该考虑到人们能够切换浏览器,而且你的目标受众群体实际使用 IE11 的比例可能要低得多人员(例如:如果你定位的是年轻人)或技术爱好者)。

  • 与不支持 IE11 所失去的金钱相比,支持 IE11 是否会给你带来更多的收入?为 IE11 开发不只是使用 Babel。你还需要在该浏览器上测试所有功能,因为即使用了 Babel,其中一些功能也会受到损坏,然后找到所有这些问题的修复程序。间接费用可能不值得。

同样,使用原声函数比 Babel 的已编译代码的速度最多可提高3倍,正如这个基准测试所强调的那样:www.inovex.de/blog/node-j… Babel 还会增加包的大小,最后,在开发时会增加构建时间。所以为什么要在每个项目中都使用 Babel 呢!

与使用原生函数相比,Babel 降低了代码执行速度,增加了包大小,并增加了构建时间。你真的在每个项目中都需要它吗?

为什么要添加诸如 let 之类的新关键字而不是进行更新?

你可能想知道为什么 JS 引入 let 而不是改进现有的 var关键字。答案很简单:这样做是为了保持向后兼容性。你不想破坏 web,对吧? (我是认真的!)

那么 Typescript 呢?

Typescript 的规则是第 3 阶段的提案。

在哪里可以找到更多信息?

Github 和官方网站在这里:

github.com/tc39/propos…

tc39.es/?source=pos…

欢迎关注前端公众号:前端先锋,免费领取webpack从入门到进阶,全系列教程。