2024 年 1 月 4 日

Polyfill 和转换器

JavaScript 语言在不断发展。针对该语言的新提案会定期出现,这些提案会得到分析,如果被认为有价值,则会添加到 https://tc39.github.io/ecma262/ 中的列表中,然后进入 规范

JavaScript 引擎背后的团队对首先要实现的内容有自己的想法。他们可能会决定实现处于草稿状态的提案,并推迟规范中已有的内容,因为它们不太有趣或更难实现。

因此,引擎只实现标准的一部分是很常见的。

查看语言特性当前支持状态的良好页面是 https://compat-table.github.io/compat-table/es6/(它很大,我们还有很多东西要学习)。

作为程序员,我们希望使用最新特性。越好的东西越好!

另一方面,如何让我们的现代代码在尚未理解最新特性的旧引擎上运行?

有两种工具可以做到这一点

  1. 转译器。
  2. 垫片。

在这里,在本章中,我们的目的是了解它们的工作原理以及它们在 Web 开发中的位置。

转译器

转译器是一种将源代码转换为另一种源代码的特殊软件。它可以解析(“读取和理解”)现代代码,并使用较旧的语法结构对其进行重写,以便它也能在过时的引擎中运行。

例如,2020 年之前的 JavaScript 没有“空值合并运算符”??。因此,如果访问者使用过时的浏览器,它可能无法理解诸如 height = height ?? 100 之类的代码。

转译器将分析我们的代码并将 height ?? 100 重写为 (height !== undefined && height !== null) ? height : 100

// before running the transpiler
height = height ?? 100;

// after running the transpiler
height = (height !== undefined && height !== null) ? height : 100;

现在,重写的代码适用于较旧的 JavaScript 引擎。

通常,开发人员在自己的计算机上运行转译器,然后将转译后的代码部署到服务器。

说到名称,Babel 是最著名的转译器之一。

现代项目构建系统(例如 webpack)提供了一种在每次代码更改时自动运行转译器的方法,因此可以非常轻松地将其集成到开发过程中。

垫片

新的语言特性不仅可能包括语法结构和运算符,还可能包括内置函数。

例如,Math.trunc(n) 是一个“截断”数字小数部分的函数,例如 Math.trunc(1.23) 返回 1

在一些(非常过时的)JavaScript 引擎中,没有 Math.trunc,因此此类代码将失败。

由于我们正在讨论新函数,而不是语法更改,因此这里不需要转译任何内容。我们只需要声明缺失的函数即可。

更新/添加新函数的脚本称为“polyfill”。它“填补”空白并添加缺失的实现。

对于此特定情况,Math.trunc 的 polyfill 是一个实现它的脚本,如下所示

if (!Math.trunc) { // if no such function
  // implement it
  Math.trunc = function(number) {
    // Math.ceil and Math.floor exist even in ancient JavaScript engines
    // they are covered later in the tutorial
    return number < 0 ? Math.ceil(number) : Math.floor(number);
  };
}

JavaScript 是一种高度动态的语言。脚本可以添加/修改任何函数,甚至是内置函数。

两个有趣的 polyfill 库是

  • core js 支持很多,允许只包含需要的特性。
  • polyfill.io 服务提供带有 polyfill 的脚本,具体取决于特性和用户的浏览器。

总结

在本章中,我们希望激励你学习现代甚至“前沿”的语言特性,即使它们尚未得到 JavaScript 引擎的良好支持。

只是不要忘记使用转换器(如果使用现代语法或运算符)和 polyfill(添加可能缺失的函数)。它们将确保代码正常工作。

例如,稍后当你熟悉 JavaScript 时,你可以基于 webpackbabel-loader 插件设置一个代码构建系统。

展示各种特性当前支持状态的良好资源

附言:Google Chrome 通常是最符合语言特性的,如果教程演示失败,请尝试使用它。不过,大多数教程演示都可以与任何现代浏览器一起使用。

教程地图

评论

在评论之前阅读此内容…
  • 如果你有改进建议 - 请 提交 GitHub 问题 或提交拉取请求,而不是评论。
  • 如果你无法理解文章中的某些内容 – 请详细说明。
  • 要插入几行代码,请使用 <code> 标记,对于多行 – 将它们包装在 <pre> 标记中,对于 10 行以上 – 使用沙箱(plnkrjsbincodepen…)