将 ES7 特性转译到 ES5
BabelJS - 将 ES2016 (ES7) 特性转译为 ES5
Section titled “BabelJS - 将 ES2016 (ES7) 特性转译为 ES5”ECMAScript 2016(以前称为 ES7)为 JavaScript 引入了几个值得注意的特性。尽管现代浏览器对这些特性有很好的支持,但如果您要针对较旧的环境,可能需要将它们转译为 ES5。BabelJS,特别是结合 @babel/preset-env,能够处理这些转换。
ES2016 中添加的主要特性是:
- 指数运算符 (Exponentiation Operator) (
**) - Array.prototype.includes()
(注意:Async/Await 通常与这个时期相关联,但它在 ES2017 中正式标准化。我们将在单独的章节或作为 ES2017 特性的一部分介绍它的转译,但原理是相似的。)
我们将重点介绍如何将这些特性转译为 ES5。默认情况下,未指定目标的 @babel/preset-env 会将代码转译为 ES5。对于像 Array.prototype.includes() 这样的特性,Babel 不能仅转译语法;它是一个新方法。这需要使用 Polyfill(垫片)。
1. 指数运算符 (**)
Section titled “1. 指数运算符 (**)”指数运算符为 Math.pow() 提供了一种简写方式。
ES2016 代码(示例:exponentiation.js)
Section titled “ES2016 代码(示例:exponentiation.js)”let num = 2;let powerOfThree = num ** 3; // 2 to the power of 3 // 2 的 3 次方console.log(`${num} raised to the power of 3 is ${powerOfThree}`); // Outputs: 2 raised to the power of 3 is 8 // 输出:2 的 3 次方是 8
let squared = 5 ** 2;console.log(`5 squared is ${squared}`); // Outputs: 5 squared is 25 // 输出:5 的平方是 25要转译这段代码,请确保您已配置 Babel(例如,使用包含 @babel/preset-env 的 babel.config.json)。
Babel 配置 (babel.config.json)
Section titled “Babel 配置 (babel.config.json)”{ "presets": ["@babel/preset-env"]}npx babel exponentiation.js --out-file exponentiation_es5.js转译后的 ES5 代码 (exponentiation_es5.js)
Section titled “转译后的 ES5 代码 (exponentiation_es5.js)”"use strict";
var num = 2;var powerOfThree = Math.pow(num, 3); // 2 to the power of 3 // 2 的 3 次方
console.log("".concat(num, " raised to the power of 3 is ").concat(powerOfThree)); // Outputs: 2 raised to the power of 3 is 8 // 输出:2 的 3 次方是 8
var squared = Math.pow(5, 2);console.log("5 squared is ".concat(squared)); // Outputs: 5 squared is 25 // 输出:5 的平方是 25Babel 正确地将 ** 运算符转换为它的等效 Math.pow() 方法,该方法在所有 ES5 环境中都可用。
2. Array.prototype.includes()
Section titled “2. Array.prototype.includes()”Array.prototype.includes() 是一个方便的方法,用于检查数组是否包含某个元素,返回 true 或 false。与指数运算符不同,这是一个添加到 Array.prototype 上的新方法。Babel 不能简单地为此转译语法;它需要一个 polyfill 来在缺少 includes 方法的环境中提供其功能。
ES2016 代码(示例:array_includes.js)
Section titled “ES2016 代码(示例:array_includes.js)”let numbers = [1, 2, 3, 4, 5];console.log(numbers.includes(3)); // true // 真console.log(numbers.includes(6)); // false // 假
let pets = ['cat', 'dog', 'bat'];console.log(pets.includes('cat')); // true // 真console.log(pets.includes('hamster')); // false // 假如果您只使用 @babel/preset-env 而不配置 polyfill 来转译这段代码,JavaScript 语法本身(方法调用)将基本保持不变,因为它是一个有效的语法。然而,它在没有 Array.prototype.includes 的旧版浏览器中将无法工作。
转译后的 ES5 代码(语法上,尚未应用 polyfill)
Section titled “转译后的 ES5 代码(语法上,尚未应用 polyfill)”"use strict";
var numbers = [1, 2, 3, 4, 5];console.log(numbers.includes(3)); // true in modern env, error or undefined in old env // 在现代环境为 true,在旧环境可能报错或 undefinedconsole.log(numbers.includes(6)); // false in modern env, error or undefined in old env // 在现代环境为 false,在旧环境可能报错或 undefined
var pets = ['cat', 'dog', 'bat'];console.log(pets.includes('cat')); // true // 真console.log(pets.includes('hamster')); // false // 假使用 Polyfill 使其工作
Section titled “使用 Polyfill 使其工作”为了使 Array.prototype.includes() 在较旧的环境中工作,您需要提供一个 polyfill。使用现代 Babel 的推荐方式是使用 core-js。您可以配置 @babel/preset-env,使其根据您的代码用法和目标环境自动从 core-js 中包含 polyfill。
- 安装
core-js:
npm install --save core-js- 更新
babel.config.json:
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", // or "entry" // 或者 "entry" "corejs": 3 // Specify core-js version // 指定 core-js 版本 } ] ]}使用 "useBuiltIns": "usage" 时,Babel 会分析您的代码,并仅针对您使用的、且目标环境不支持的特性添加特定的 import 'core-js/...' 语句。如果未指定目标环境,它会假设为较旧的环境。
现在转译 array_includes.js 文件时,Babel 会在文件顶部添加类似的 import 语句:
// Example of what Babel might add at the top of array_includes_es5.js: // Babel 可能在 array_includes_es5.js 文件顶部添加的示例:// import "core-js/modules/es.array.includes.js";// (if using a bundler, otherwise it might be different) // (如果使用打包工具,否则可能会有所不同)
"use strict";// ... rest of your transpiled code ... // ... 其余的转译代码 ...var numbers = [1, 2, 3, 4, 5];console.log(numbers.includes(3));// ...这个导入的 core-js 模块在缺少 Array.prototype.includes 实现时会提供它。现在,即使在支持 ES5 但缺少 includes 的旧版浏览器中,代码也能正确工作。
或者,使用 "useBuiltIns": "entry" 需要您在应用程序的入口点 (entry point) 添加 import "core-js"; 和 import "regenerator-runtime/runtime";(如果使用了 async/generators)。然后 Babel 会根据您的目标环境将这些语句替换为特定的导入。
在浏览器中测试
Section titled “在浏览器中测试”要在浏览器中测试使用 polyfill 的代码,您通常需要打包 (bundle) 您的 JavaScript 代码(例如,使用 Webpack 或 Rollup),这将解析 core-js 的 import 语句。然后,您的 HTML 文件将包含这个打包后的文件。
test.html(假设打包后的输出文件为 bundle.js):
<!DOCTYPE html><html><head> <title>BabelJS ES2016 Test</title> // BabelJS ES2016 测试</head><body> <p>Check the console for output.</p> // 查看控制台输出。 <script src="bundle.js"></script> <!-- bundle.js would contain transpiled code + core-js polyfills --> <!-- bundle.js 将包含转译后的代码 + core-js polyfills --></body></html>当您在旧版浏览器中打开这个 HTML 文件时,控制台应该会正确显示:
truefalsetruefalse这展示了 Babel 的强大之处,它不仅可以转换语法,还可以结合像 core-js 这样的 polyfill 库,在较旧的 JavaScript 环境中提供缺失的功能。
有关 polyfill 的更多详细信息,请参阅关于 Polyfills 的专门章节以及 Babel 和 core-js 的官方文档。