Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。
Domenic Denicola关于ECMAScript的提案“import()”已经进入到第三阶段了。它允许动态加载ECMAScript模块,这篇博文对其进行了说明。
1.ECMAScript模块是静态的
ECMAScript模块是完全静态的。你必须在编译时指明你要导入和导出的模块,并且它不能在运行时响应变化。这样做有一些优势,尤其涉及到工具的时候(参见Exploring ES6中的解释)。
导入的静态结构在语法上进行了两方面的加强。参考如下示例:
首先,这个导入定义只能出现在模块的最上级。这可以阻止你导入一个含有条件语句或者事件句柄的模块。
其次,模块说明符‘./dir/someModule.js’是固定的,你无法在运行时去计算它(通过函数调用等)。
2.这个提案允许动态调用模块
提案中推荐的加载模块的操作符像下面这样动态的工作:
这个操作符使用起来像函数一样。它的参数是带有模块说明符的字符串,和import定义中使用的模块说明符格式相同。与后者相比,这个参数可以是任意的结果可以被强制转换为字符串的表达式。
这个函数调用的结果是一个promise函数。只要模块加载完成,就会把promise赋值给结果。
尽管‘import()’像一个函数一样运行,它只是一个操作符。为了将模块操作符关联到当前模块,它需要知道它是被哪一个模块所调用。常规函数没有直接的方式来完成这个功能。
3.用例
3.1按需加载代码
一些网页应用的功能并不需要在启动时使用,它就可以按需加载。然后就能用上import()了,因为你可以将这种功能放入模块。例如:
3.2模块的条件加载
有时候你可能需要根据条件是否为真来加载一个模块。例如加载一个polyfill到传统平台上,代码大致如下:
3.3计算出模块说明符
对于国际化的应用,它有助于动态计算出模块说明符:
4.小提示
4.1通过析构获取外部接口
析构可以让我们获取外部接口:
4.2获取默认外部接口
对于默认外部接口,你需要知道default是一个关键字,可以通过点操作符将它作为一个属性名使用:
但是你不能将它当做变量名使用:
4.3动态加载多个模块
你可以通过Promise.all()来动态同时加载多个模块:
4.4异步函数与import()
import()返回promise对象,这意味着你可以通过async function(是ECMAScript2017的一部分)使用import()并得到更漂亮的语法:
在最上层模块或者脚本中,你会立即发现调用的异步箭头函数很有用:
5.对import()的支持Node.js:Guy Bedford在node-es-module-loader中提供一个可执行的支持ES6模块语法和import()的Node.js
webpack v1:babel-plugin-dynamic-import-webpack是一个babel插件将import()转换成了require.ensure()
webpack v2:(v2.1.0-beta28及以后版本):通过import()支持code-splitting。
6.延伸阅读Exploring ES6中的章节“Modules”
Exploring ES2016和ES2017中的章节“Async functions”
英文原文:http://www.2ality.com/2017/01/import-operator.html
译者:lucklyxhj