为什么我需要 @babel/polyfill,使用 Babel?

gre*_*emo 6 javascript ecmascript-6 babeljs

我正在学习巨大的 JavaScript 生态系统,但我无法理解以下内容。

Babel是一个转译器,来自官网:

Babel 是一个工具链,主要用于将 ECMAScript 2015+ 代码转换为当前和旧版本浏览器或环境中向后兼容的 JavaScript 版本。

由于我使用的是@babel/preset-envPresent,我认为根据我的浏览器列表,这应该足以编写ES6+ 代码并将其转换为一些兼容的代码。

然后,我进入了这个: https: //babeljs.io/docs/en/babel-polyfill,建议使用@babel/polyfill而不是

import "core-js/stable";
import "regenerator-runtime/runtime";
Run Code Online (Sandbox Code Playgroud)

而不是已弃用的@babel/polyfill. 现在我知道什么是 polyfill,例如,我使用了 Intersection Observer polyfill。

所以我的问题是这是 Babel 提供的“自动”功能吗?某种可以自动填充我的代码的插件?他们谈论的两个库是什么?如果 Babel 应该自己做的话,为什么我需要这两个额外的包来使我的代码兼容 ES5?考虑一下Object.assign:它只能在 IE11 中使用 package.json 来工作core-js。为什么 Babel 没有转译它?

编辑:我错误地阅读了这篇文章,但我的问题仍然是一样的。

eha*_*hab 11

polyfill 和转译都使您能够在旧环境中使用新功能(例如,考虑旧浏览器与新浏览器),主要区别在于,polyfill 是通过在旧环境本身中实现该功能来实现这一点的。因此,如果我们使用 ES6 ES5 术语,polyfill 使您能够通过在 ES5 中实现来使用新功能,但是某些新功能永远无法在 ES5 中实现,例如考虑一下 ES6 引入的箭头语法 - 这就是转译的地方需要。

需要转译的一个例子是箭头语法 (() => {}),因为你永远无法在 ES5 中实现它,而一个可以使用 polyfill 的例子是如果你想实现该方法String.prototype.includes。可以这样实现:

// taken from mdn
if (!String.prototype.includes) {
  String.prototype.includes = function(search, start) {
    'use strict';

    if (search instanceof RegExp) {
      throw TypeError('first argument must not be a RegExp');
    } 
    if (start === undefined) { start = 0; }
    return this.indexOf(search, start) !== -1;
  };
}
Run Code Online (Sandbox Code Playgroud)

现在另一个重要的区别是,polyfill 将使用本机功能(如果存在),但转译则不会。由此得出的结论是,出于安全和性能方面的原因,polyfills 应该优先于转译。

最后一个区别是转译是关于语言语法的,而 polyfill 是关于语言语法和本机浏览器 API 的。

长话短说:转译是在编译时进行的,而 polyfill 是在运行时进行的。

现在区别已经很清楚了,我们可以看到,为了使用新代码和新功能,Babel 使用了这两种策略。主要准则是尽可能使用polyfill;否则,转译(新语法需要转译,而新语法本身永远无法在旧的 ES5 环境中实现)。因此,您需要将 core-js 导入到可以通过转译启用的 polyfill 功能,但最好使用 polyfill 来实现它们

让我们以一些代码为例,来区分两者:

const f = (str) => {
  return str.includes('fun')
}
Run Code Online (Sandbox Code Playgroud)

Babel 要做的就是将该代码转换为如下所示的内容:

var f = function f() {
 // notice that `.includes()` stays. Even though this is
 // an ES6 feature, it stays because
 // Babel does not transpile it.
 // 
 // the following code will break if you don't import
 // a polyfill using core-js or any other polyfill library
 return str.includes('fun');
}
Run Code Online (Sandbox Code Playgroud)

我已经删掉了很多 Babel 转译输出的内容,如果你想看的话可以在这里阅读。

现在回答你的问题 Babel 是否使用自动的东西来做到这一点。答案是肯定的,那就是@babel/preset-env,它将根据您的目标环境自动配置您所需的转译过程和 polyfill。


Dan*_*ite 1

Babel 只提供语言操作(即语法),而不提供所需对象的底层类型(即作用的名词)。