Babel 是一个 JavaScript 编译器,可将咱们代码中的 ES6 语法转换为 ES5 的语法,使咱们的代码能在不支持 ES6 语法的环境中正常运行。配合一些插件,咱们甚至能直接使用 ES6 标准的一些新特性,而无需等待各大浏览器的实现,也无需担心兼容性。css
新建 babel_test
文件夹,在命令行里进入该文件夹,并执行以下命令:html
npm init -y # 生成 package.json 文件 npm i -D babel-cli babel-preset-env npm i -S babel-polyfill
在编写本文章时,上面依赖包的最新版本分别为 babel-cli 6.26.0、babel-preset-env 1.6.一、babel-polyfill 6.26.0,若是安装的版本不一致,可能会获得不同的结果。
新建 .bablerc
文件,内容以下:node
{ "presets": ["env"] }
.bablerc
是 Babel 的默认配置文件,运行 Babel 时会自动读取该文件的配置。上面 .bablerc
文件配置的意思是对代码进行彻底的转换。git
新建 source.js
文件,内容以下:es6
// 这里的代码无任何意义,只用做示例 const sayHi = () => { const str = 'Hello World!'; const arr = [...str]; alert(arr.join('')); };
...
是 ES6 语法,详情可参考
http://es6.ruanyifeng.com/#docs/array
执行如下命令就能够把 source.js
的代码转换为 ES5 的语法,并把结果输出到 target.js
。github
./node_modules/babel-cli/bin/babel.js source.js -o target.js
babel-cli 的详细命令可参考 https://babeljs.cn/docs/usage/cli/
target.js
的内容最终以下:web
'use strict'; function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var sayHi = function sayHi() { var str = 'Hello World!'; var arr = [].concat(_toConsumableArray(str)); alert(arr.join('')); };
能够看到 Babel 在 target.js
添加了 _toConsumableArray
函数,并将 [...str]
替换成了 [].concat(_toConsumableArray(str))
。到这里咱们已经成功的将代码中的 ES6 语法转换为 ES5 语法,Babel 的使用就是这么简单。chrome
若是咱们仔细查看上文中的 target.js
,会发现 Babel 添加的 _toConsumableArray
函数居然使用了 ES6 的特性 Array.from
,也就是说咱们使用 Babel 转换后代码里可能还会存在 ES6 的东西!这个问题能够参考 https://www.zhihu.com/question/49382420。npm
这里咱们须要重点注意的是:json
Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,好比Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(好比Object.assign)都不会转码。—— 《ECMAScript 6入门》
为了确保转换后的代码能正常的运行,最好在代码以前引入 babel-polyfill(这是一个实现了部分 ES6 特性的包)。
<!-- 在 HTML 文件中先引入 babel-polyfill 再引入 target.js --> <!-- src 属性里的 6.26.0 是本文章编写时 babel-polyfill 的最新稳定版本,你可能须要根据实际引入对应的版本 --> <script src="https://cdn.bootcss.com/babel-polyfill/6.26.0/polyfill.min.js"></script> <script src="target.js"></script>
至此,咱们能够放心的随意使用 ES6 的特性了。
其实现代浏览器或多或少都实现了部分 ES6 标准,如 Chrome v64 甚至已实现了 97% 的功能。若是咱们肯定咱们的代码只运行在 Chrome v64 ,那么像 source.js
中的箭头函数则无需转换,由于 Chrome v64 已经支持这样的语法了。同理咱们也无需引入整个 babel-polyfill ,只需引入其中 Chrome v64 不支持的部分便可。
Babel 的强大之处在这里更能获得体现。当咱们配置了代码的运行环境以后,Babel 会自动判断该环境对 ES6 的实现程度,而后只把源代码中该环境不支持的语法进行转换。若是咱们在源代码中利用模块化的方式引入 babel-polyfill ,Babel 也会对其进行优化,只引入该环境还没有实现的模块。下面就让咱们来体现一下这强大的功能。
修改配置文件 .babelrc
,内容以下:
{ "presets": [ [ "env", { "targets": { // 配置代码的运行环境 "chrome": 64 }, "useBuiltIns": true // 开启对 babel-polyfill 的优化 } ] ] }
修改source.js
,内容以下:
// 使用 ES6 的模块化标准引入 babel-polyfill import 'babel-polyfill'; const sayHi = () => { const str = 'Hello World!'; const arr = [...str]; alert(arr.join('')); };
运行命令编译成功后,target.js
的内容以下:
'use strict'; require('core-js/modules/web.timers'); require('core-js/modules/web.immediate'); require('core-js/modules/web.dom.iterable'); const sayHi = () => { const str = 'Hello World!'; const arr = [...str]; alert(arr.join('')); };
能够看到,箭头函数和 ...str
都没有变化,由于 Chrome v64 已经支持这样的语法。import 'babel-polyfill'
则变成了用 CommonJS 的方式引入了三个小模块,这是 Babel 经过查询 compat-table 得知 Chrome v64 还没有实现的特性后添加的模块。
以上即是 Babel 的一些基本使用了。
最后说明一下:
target.js
使用了 CommonJS 的模块化规范,这还须要一些构建工具对其进一步编译才能在 Chrome v64 上运行。