PolyFill JS

2025年3月18日 | 阅读 10 分钟

Polyfill JS 为浏览器提供了对它们原生不支持的方法和事件的支持。简单来说,Polyfill JS 是一些脚本代码,它提供了在旧版 Web 浏览器上支持现代功能的能力。

例如,它可以用来改变旧版 Internet Explorer(如 IE7)中 text-shadow 的功能,通过使用 IE filters 属性;或者它也可以通过使用一些 JavaScript 代码动态更新网页的 rem 值或 media query。它可以根据开发者的需求更新许多其他 Web 浏览器属性。

我们不专门使用 polyfills 来体验应用程序更好的性能和功能。JavaScript API 的原生实现比 polyfills 提供更好、更快的性能。例如,如果我们通过 polyfills 的 Object.create 方法创建一个对象,它将只包含使用 Object.create 方法的非原生实现可以实现的功能。相反,如果我们遵循原生方法,它将更具功能性和可访问性。

大多数时候,polyfills 是为了满足某些特定需求或解决 Web 浏览器以不同方式实现同一功能的浏览器兼容性问题而需要的。为了以符合标准的方式访问功能,它在某些浏览器中使用了非标准功能。

尽管现在 polyfilling 的使用非常罕见。在 IE6 及更早版本流行的日子里,它非常有用。那时,浏览器被设计成以不同的方式处理 JavaScript。如今,现代浏览器几乎以相似的方式处理 JavaScript。

那时,JQuery 的第一个版本引入了 Polyfill。它汇集了多个浏览器特定的解决方法,通过将不同浏览器的功能合并到一个 API 中,从而帮助 JavaScript 开发人员。

那时,开发人员在处理跨浏览器功能方面面临着重大问题。旧的浏览器存在如此多的差异,以至于开发人员需要开发具有不同方法并且根据用户浏览器具有截然不同的用户界面的网站。因此,当时的开发人员需要一小部分支持跨浏览器功能的 JavaScript API。

如今,使用 Polyfill 来处理跨浏览器实现的情况非常罕见,因为现代浏览器大多根据标准语义实现了大量的 JavaScript API。

让我们了解一下如何在 JavaScript 中使用 polyfills。

如何在 JavaScript 中使用 Polyfill?

如今,Web 充斥着许多现代且广泛的新技术。随着新技术的引入,许多新功能可能无法被旧浏览器支持。Web 上有许多具有不同功能的浏览器,它们每天都在更新。最新版的 Web 浏览器支持许多功能,并对现有功能进行了一些改进。最新版本可以执行许多旧版本无法完成的任务。但是,在开发应用程序时,有必要确保它能够支持所有 Web 浏览器并以类似的方式提供结果。

尽管如此,将最新功能集成到浏览器中并确保应用程序的行为在不同浏览器上不会损害功能性,这是一个具有挑战性的任务。

幸运的是,我们有 Polyfills;借助 Polyfills,我们可以实现覆盖浏览器默认行为的功能,并强制应用程序按预期显示输出。

Polyfill 这个术语是由 Remy Sharp 引入的,他想要一个术语来描述当浏览器不支持某个 API 时,使用 JavaScript 重现该 API 的功能。

他在博客中描述道,他想要一个容易发音的词,并且能让人对它的作用有一个模糊的认识。Polyfill 这个词是 Poly 和 Fills 这两个词的组合;Poly 意味着可以使用任意数量的技术来解决,并且不局限于仅使用 JavaScript 来完成;而 fill 则是填补浏览器中所需技术的“空缺”,而不管 Web 浏览器的版本。

Polyfills 的特性

以下是 Polyfills 的一些特性和原则:

  • 首先理解 polyfills 的范围和含义;Poly 意味着可以使用多种方法来解决,并且不限于仅使用 JavaScript 原生方法,而 fill 意味着它将满足用户的需求,并弥合不同浏览器之间的差距,而不管技术。
  • 可以将其理解为一种工具,可以填补空白和裂缝,使任何不完美之处变得平滑。
  • 较新版本的 JavaScript,如 ES6,引入了许多新功能,但仍然没有为 Web 浏览器提供完全支持。如果我们使用 ES6、ES7 或 ES8 的最新语法特性,那么它可能在旧版本浏览器中无法正常工作。
  • 除了语法和运算符,新功能还可能包含一些新的方法和函数。因此,我们使用 polyfills 和转译器来满足用户的请求。
  • 这是一种技术,它允许我们通过一些代码为具有兼容性问题的旧浏览器添加功能。

以下是一些需要明确定义 polyfill 支持才能在旧版 Web 浏览器中实现功能的特性:

  • Promises,
  • Array Methods,例如 Array.from、Array.includes、Array.of 等。
  • Map Object
  • Set
  • 符号
  • Object Methods,例如 object.values、Object.keys 等。

如何使用 polyfills 在旧浏览器版本中实现最新的 JavaScript 功能

让我们了解一下 Polyfill 在 JavaScript 中是如何工作的。我们将使用 node JS 环境在旧版本中实现较新的功能。

我们将使用相同的 ES6 功能,例如 Promises,然后将其转换为 ES5 代码,以避免在旧浏览器中出现兼容性问题。我们将从我们的 node modules 中将此 ES5 代码 babel-polyfill 文件添加到我们的 index.html 文件中,以便它可以在 Web 浏览器上编译和运行。

请按照以下步骤来实现 polyfill 功能:

步骤 1:创建项目并设置环境

我们将在应用程序中包含一个 babel 转译器,以将 ES6 功能转换为向后兼容的 JavaScript 版本,从而为所有旧版和新版浏览器提供支持。Babel 转译器是一个开源工具,对所有人免费。

要创建基本项目并设置环境,我们需要在机器上安装 node JS 环境。node JS 环境将帮助 babel-polyfill 运行。

让我们创建一个新目录并在其中打开终端。

现在,运行以下命令初始化项目

按 Enter 键执行。它将提供以下输出:

输出

npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
Wrote to E:\polyfill\package.json:
{
  "name": "polyfill",
  "version": "1.0.0",
  "description": ",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": ",
  "license": "ISC"
}

我们需要安装 Babel cli、core 和 preset。执行以下命令安装 babel cli、core 和 preset:

上述命令执行后,它将开始运行安装程序文件,并提供有关已添加的包和 npm 版本的信息。它将提供以下输出:

npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.

added 196 packages, and audited 197 packages in 49s

11 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
npm notice
npm notice New major version of npm available! 8.11.0 -> 9.6.7
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.6.7
npm notice Run npm install -g [email protected] to update!
npm notice

文件夹结构将如下所示:

PolyFill JS

package.json 文件包含项目所有已安装的依赖项,而 package-lock.json 是 npm 在编译时自动生成并在安装或更新包时更新的。

当我们安装 Babel-core 包时,它还会随之安装 Babel-polyfill 包。此外,我们需要将 es2015 添加到 presets 中,以便将代码转换为与旧浏览器兼容的代码。

我们需要创建一个 Babel 配置文件,它将放置在项目的根目录中。

在项目的根目录创建一个 .babelrc 文件,并在其中添加以下 preset 值:

现在,我们的文件浏览器将如下所示:

PolyFill JS

步骤 2:创建 JavaScript 文件

现在,创建一个包含一些现代 JavaScript 概念的 JavaScript 文件。我们将使用 ES6 功能和 Promises 来使用 Polyfill 功能。

创建一个 index.js 文件并编写以下代码。在下面的代码中,我们使用了 Polyfill 的概念以及 Promises,并将在一两秒的时间间隔后记录一条问候消息。

Index.js

上面的代码使用了 ES6 的最新功能。现在,我们将把这段代码转换为 ES5,以便它可以在旧浏览器上正常运行。

步骤 3:将 ES6 功能转换为 ES5

要将 index.js 文件中的 ES6 功能转换为 ES5 代码,请执行以下命令:

上述命令执行后,它将根据指定的名称创建一个具有 ES5 代码的新文件。

请看生成文件的以下代码:

index_es5.js

在这里,在上面的代码中,我们可以看到 index_es5.js 文件中生成的代码与 ES5 语法兼容。例如,我们可以看到箭头函数语法已自动转换为传统的函数关键字。

步骤 4:将 Polyfill 与最终编译后的 JavaScript 一起包含

现在,我们需要将 Polyfill 与转换后的 JavaScript 代码一起包含在新文件中。为此,让我们创建一个名为 index.html 的 html 文件,其中包含一些标题。我们将实现的特性绑定到某些 <span /> 标签中,并将描述内容绑定到 <p /> 标签中,它将在 2 秒后显示,如指定时间所示。我们将在创建的 index.html 文件中包含 node modules 中的 babel-polyfill。

将以下脚本添加到 index.html 文件中:

<script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>

<script type="text/javascript" src="/index_es5.js"></script>

index.html 文件应放置在项目的根目录中。以下是我们的 html 代码:

Index.html

我们的最终文件夹结构将如下所示:

PolyFill JS

步骤 5:运行我们的应用程序

为了运行我们的应用程序,我们需要通过服务器启动它。所以,这里我们使用 Vs-code 中的 live server 插件来运行我们的应用程序。点击代码编辑器右下角的 Go Live 选项,或者右键单击文件并选择 live server 选项。它将在配置的端口号上启动应用程序。

最终输出

我们已将 polyfill 功能实现到我们的应用程序中,以便我们可以在旧浏览器中使用 ES6 功能。我们使用了 Promises,并通过 setTimeout 方法在一段时间后显示输出。因此,通过 ID 绑定到某些标签的内容将在指定时间后显示。此外,此代码与仅支持 ES5 功能的浏览器兼容。

考虑下面的输出

PolyFill JS

2 秒后,输出:

PolyFill JS

结论

从上面的输出可以看到,通过使用 Polyfill 概念;我们已经将 ES6 Promises 功能实现到了 ES5 代码中,并实现了相同的功能。同样,我们可以将 JavaScript 中引入的最新版本中的其他 JavaScript 功能转换为旧版本兼容的版本。

尽管如此,如今,polyfills 的使用几乎不再需要,因为现代浏览器以类似的方式处理 JavaScript,但可能存在不同的用例,您需要在不同场景下遵循这种方法。