前言
在使用 Babel 进行 JavaScript 代码转换的过程中,你可能会遇到一些类似于“'Promise' 没有被定义”的错误提示。那么这是为什么呢?为什么 Babel 不能直接识别 JavaScript 内置对象呢?本文将会为你解答这个问题,并针对这个问题给出指导意义。
JavaScript 的内置对象
JavaScript 内置对象一般指全局对象(Global Object)例如 Promise
, Array
, Object
等等,它们在任何 JavaScript 环境中都是可用的,也就是说它们被默认定义在 JavaScript 引擎中了,不需要额外引入。
Babel 的转换过程
Babel 作为一个 JavaScript 编译器,可以将 ES6 / ES7 代码转换为通用的 ES5 代码,以在更多版本的浏览器上运行。Babel 的转换过程,是通过插件机制将代码转换为 AST 然后再转换为新的 JavaScript 代码。
转换原理图:
为什么 Babel 不能识别 JavaScript 的内置对象?
以上面的代码为例:
const promise = new Promise(function(resolve, reject){ //do something });
ES6 写法中使用了内置对象 Promise,但当这段代码经过 Babel 编译后,却变成了这样子:
var promise = new Promise(function (resolve, reject) { //do something });
可以看出纯粹的 Promise 对象不再引入,仅仅是将 Promise 对象转换为了相应的 ES5 代码,并没有引入 Promise 构造函数的定义。因此,当你的浏览器不支持 Promise 对象时,代码执行就会报错了。
解决方案
要让 Babel 编译有效地识别内置对象,最好的方式是引入相应的 Polyfill。Polyfill 是一个 JavaScript 脚本,包含了许多可以补足早期浏览器或旧版浏览器缺陷的 API。 这意味着如果你想要使用一些现代的 JavaScript API,则可以通过引入相应的 Polyfill来实现。
引入 Promise 的 Polyfill 示例:
import "core-js/stable"; import "regenerator-runtime/runtime"; const promise = new Promise(function (resolve, reject) { // do something });
上述代码中,我们首先引入了 core-js
模块,核心代码含有对所有新 API 的 polyfill。之后,引入了 regenerator-runtime/runtime
模块,它用于在不支持任何生成器的环境中启用 ECMAScript 6 生成器函数。
通过引入这些 Polyfill,就可以使得 Babel 正确转换出编译后的代码,使得代码可以在不同版本的浏览器上运行,同时方便了我们使用新前端技术。
总结
在前端开发中,我们不可避免地遇到使用新 API 的情况,但是这些新 API 往往是当前一些较早的浏览器不支持的。Babel 可以帮助我们将新的 JavaScript 特性转换为通用的 ES5 代码,但是由于它不能识别 JavaScript 内置对象,导致在使用这些对象时我们需要手动加入相应的 Polyfill。因此,合理引入 Polyfill 也非常重要,当使用某个内置对象时,务必要先了解该对象的 Polyfill 方法,避免因缺陷而影响代码的正常运行。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6467a7d2968c7c53b080341a