前端工程搭建入门(六)支持es6新特性
背景
- 因为es6发布较晚,各大浏览器还没完全支持es6语法以及其特性,现阶段开发者大多采用babel进行代码语法转换
Babel has support for the latest version of JavaScript through syntax transformers. These plugins allow you to use new syntax, right now without waiting for browser support.
Babel通过语法变换器支持最新版本的JavaScript。 这些插件允许您立即使用新语法,而无需等待浏览器支持。 - 但是 babel 只是转换语法,并不能转换新特性,如箭头函数以及一些新的方法拓展
Since Babel only transforms syntax (like arrow functions), you can use babel-polyfill in order to support new globals such as Promise or new native methods like String.padStart (left-pad). It uses core-js and regenerator.
由于Babel只转换语法(如箭头函数),因此您可以使用babel-polyfill来支持新的全局变量(如Promise)或新的本机方法(如String.padStart(left-pad))。 它使用core-js和regenerator。 - 除了polyfill,还可以使用 transform-runtime 进行新特性支持。具体使用方法就不说了,文档里写的很清楚,下面就只了解一下这两种方式有什么区别。
Polyfill
- 安装:
-
npm install --save babel-polyfill
(babel 6) -
npm install --save @babel/polyfill
(babel 7)
-
- 它是怎么支持
Map Set Promise async
等全局方法的?通过一个示例来了解一下:- 写了两个js文件,以便更好地了解polyfill对于多处引用是怎么处理的。
List.js
Detail.js - 两个文件几乎一模一样,打包编译,控制台输出如下:
console - 下面看一下打包之后的代码,看看这里的 async Map includes 是来自哪里 async 解析
- 可以看到,getTitle 这个 async 函数是 _asyncToGenerator 生成的,看一下 _asyncToGenerator 是哪里定义的:
_asyncToGenerator - 这个转换函数一共有4个,两次定义,两次使用。List 使用了一次,定义了一次;Detail 里使用了一次,也定义了一次。接着看 includes :
includes - 很明显,polyfill 重写了数组原型所有 es6+ 新增的方法。再看 Map 是如何转换的:
Map 定义 - 在这里定义了 Map ,这是一个全局变量,只定义了一次,再看 118 模块干了啥:
118 - 显而易见,重写了 Map 函数。
- 写了两个js文件,以便更好地了解polyfill对于多处引用是怎么处理的。
综上,polyfill 的原则就是,对于全局变量 Map Set Promise 等,以及 es6 新增的方法全部重写。async 是通过 Promise 实现的,并且每个出现引用的模块都会定义一次。
transform-runtime
- 安装(依赖 babel-runtime):
-
npm install --save-dev babel-plugin-transfrom-runtime
(babel 6) -
npm install --save babel-runtime
(babel 6) -
npm install --save-dev @babel/plugin-transfrom-runtime
(babel 7) -
npm install --save @babel/runtime
(babel 7)
-
- 按照上面的顺序,看一下它是怎么处理这些新特性的:
-
async 转换:
async
-
和 polyfill 是一样的原理,哪里引用,哪里定义。再看 includes,找了一大圈也没找到定义的地方,说明 transform-runtime 并没有对 includes 处理,官方文档说了,
"foobar".includes("foo")
这种实例方法是不会被转换的,也就是完全靠浏览器去支持了,如果浏览器不支持,就需要使用 polyfill ,所以这算是 transform-runtime 的小缺陷。 -
再看 Map ,同样,找了一圈未果,没有找到定义的地方,再看文档,完美解答了我的困惑:
-
The runtime transformer plugin does three things:
- Automatically requires babel-runtime/regenerator when you use generators/async functions.
- Automatically requires babel-runtime/core-js and maps ES6 static methods and built-ins.
- Removes the inline Babel helpers and uses the module babel-runtime/helpers instead.
What does this actually mean though? Basically, you can use built-ins such as Promise, Set, Symbol, etc., as well use all the Babel features that require a polyfill seamlessly, without global pollution, making it extremely suitable for libraries.
runtime 编译器插件做了以下三件事:
- 当你使用 generators/async 函数时,自动引入 babel-runtime/regenerator 。
- 自动引入 babel-runtime/core-js 并映射 ES6 静态方法和内置插件。
- 移除内联的 Babel helper 并使用模块 babel-runtime/helpers 代替。
这意味着什么?基本上,你可以使用诸如 Promise,Set,Symbol 等内置函数,以及所有需要 polyfill 来完成且不带来全局污染的 Babel 功能,因此非常适合作为库使用。
综上,transform-runtime 不会污染全局环境,不会污染原型,至于文档说的 沙盒环境 ,暂时没感受到,希望以后的开发过程中能够体会到其真正用意。
这些就是我一步一步去仔细体会 polyfill 和 transform-runtime 的一些区别,当然只是通过一个简单的列子,不能展现所有的实现原理,只是感受二者的基本差异。可能有错误的理解,希望大家多多指正,共同学习,共同进步 。