说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

全面解析ECMAScript 6模块系统

HTML文档下载 WORD文档下载 PDF文档下载
模块化对任何大型应用来说十分必要,ES6弥补了JavaScript缺少对模块支持的遗憾。浏览器虽对ES6模块化支持还不够,但开发者可以借助编译器将ES6模块转换成ES5。本文将系统讲解ES6模块系统所提供的各种编码方法。

【编者按】在任何一个大型应用中模块化是很常见的。ES6的模块为JavaScript提供了这个特性,并且为这些模块提供了许多选择方法来导出和引入对象。Ravi Kiran 在《Modules in ECMAScript 6 (ES6)》一文中主要讨论了ES6模块系统。以下为该文章的简译内容:

无论使用何种编程语言开发大型应用,最关键的特性就是代码模块化。这个概念在不同的编程语言里有着不同的命名,在C里为头部文件,C++和C#里为命名空间,Java中为包,名称不一样但解决的是同一问题。正如《 ECMAScript 6 – New language improvements in JavaScript》系列文章中第一篇所提到的那样,最初JavaScript并不是用来编写大量代码的,比如创建大型框架、App应用等。就在我们因为JavaScript缺少对模块的支持而编写大量代码时,开源开发者提出了一些标准,如CommoneJs模块模型、异步模块定义(AMD)以及一些库,来实现模块化。在过去几年里,这些库获得了广泛关注,并成功应用到多个企业规模级的应用程序中。

ES6为JavaScript带来了模块特性。浏览器实现这一特性还需要一段时间,因为它们必须定义一个方法来动态下载文件。在浏览器支持该特性以前,我们可以使用编译器,如 Traceur、6to5、ES6 Module Loader以及其它可以让ES6模块转换成ES5的转码器。

JavaScript模块系统的现状

CommonJS模块系统

CommonJs是一个由开源开发者组成的团队,主要围绕JavaScript实现一些API及开展研发实践。该团队提出了一个JavaScript模块规范。每个文件都可当作一个模块,并且每个文件可以访问两个对象:require和export。require用来接收字符串(模块名),并返回该模块输出的对象。export对象用来导出该模块的方法和变量。require方法返回的就是export对象。模块同步加载。服务器端JavaScript引擎Node.js就是用的这个模块系统。

异步模块定义(AMD)

AMD是一个采用异步方式加载依赖模块的模块系统。如果模块在不同文件中,它们将采用XHR进行加载。某一模块将等其所依赖的模块一一加载后才会被执行。AMD模块必须是一个函数,并作为参数传入define函数中。函数的返回值将传输给所有依赖的模块,所获得返回值又将作为参数传给模块方法。Require.js库中实现了AMD。

TypeScript模块

TypeScript,作为JavaScript的超集,也提供了一个模块系统。当它被编译时,便开始使用JavaScript模块模式。TypeScript模块使用module关键字定义,任何被输出的对象必须使用export关键字定义。import关键字用来将其它模块加载入模块中,并捕捉该模块导出的对象。TypeScript模块是同步加载的。

ES6模块系统

ES6模块系统启发于上述现有模块系统,它具有以下特性:

  1. 使用export关键词导出对象。这个关键字可以无限次使用;
  2. 使用import关键字将其它模块导入某一模块中。它可用来导入任意数量的模块;
  3. 支持模块的异步加载;
  4. 为加载模块提供编程支持。

接下来让我们通过具体编程方法看看每一个特性。

导出对象

在现有的模块系统中,每个JavaScript代码文件在ES6中都是一个模块。只有模块中的对象需要被外部调用时,模块才会输出对象,其余则都是模块的私有对象。该处理方式将细节进行封装,仅导出必要的功能。

从模块里导出对象,ES6为我们提供了不同方法,见下面的讨论。

内联导出

ES6模块里的对象可在创建它们的声明中导出。一个模块中可无数次使用export,所有的对象将被一起导出。请看下面的例子:

export class Employee{  constructor(id, name, dob){    this.id = id;    this.name=name;    this.dob= dob;  }  getAge(){    return (new Date()).getYear() - this.dob.getYear();  }}export function getEmployee(id, name, dob){  return new Employee(id, name, dob);}var emp = new Employee(1, "Rina", new Date(1987, 1, 22));

案例中的模块导出了两个对象: Employee类,getEmployee函数。因对象emp未被导出,所以其仍为模块私有。

导出一组对象

尽管内联导出很有效,但在大规模模块中,它就很难发挥作用了,因为我们可能无法追踪到模块导出来的对象。在这种情况下,更好的办法是,在模块的末尾单独进行导出声明,以导出该模块中的全部对象。

使用单独导出声明重写上一案例中的模块,结果如下:

class Employee{  constructor(id, name, dob){    this.id = id;    this.name=name;    this.dob= dob;  }  getAge(){    return (new Date()).getYear() - this.dob.getYear();  }}function getEmployee(id, name, dob){  return new Employee(id, name, dob);}var x = new Employee(1, "Rina", new Date(1987, 1, 22));export {Employee, getEmployee};

在导出时,重命名对象也是可以的。如下例所示,Employee在导出时名字改为了Associate,函数GetEmployee改名为getAssociate。

export {    Associate as Employee,    getAssociate as getEmployee  };

Default导出

使用关键字default,可将对象标注为default对象导出。default关键字在每一个模块中只能使用一次。它既可以用于内联导出,也可以用于一组对象导出声明中。

下面案例展示了在组导出语句中使用default:

export default {    Employee,    getEmployee};

导入模块

现有模块可以使用关键字import导入到其它模块。一个模块可以被导入任意数量的模块中。下文展示了导入模块的不同方式。

无对象导入

如果模块包含一些逻辑要执行,且不会导出任何对象,此类对象也可以被导入到另一模块中。如下面案例所示:

import './module1.js';

 导入默认对象

采用Default导出方式导出对象,该对象在import声明中将直接被分配给某个引用,如下例中的“d”。

import d from './module1.js';

 导入命名的对象

正如以上讨论的,一个模块可以导出许多命名对象。如果另一模块想导入这些命名对象,需要在导入声明中一一列出这些对象。举个例子:

import {Employee, getEmployee} from './module1.js';

 当然也可在同一个声明中导入默认对象和命名对象。这种情况下,默认对象必须定义一个别名,如下例。

import {default as d, Employee} from './module1.js';

 导入所有对象

以上几种情况,只有import声明中列举的对象才会被导入并被使用,而其它对象则无法在导入模块中使用。当然,这就要求用户了解哪些对象可以导出并加以利用。如果模块导出大量对象,另一模块想引入所有导出的对象,就必须使用如下声明:

import * as allFromModule1 from './module1.js';

 allFromModule1这一别名将指向所有从module1导出的对象。在导入模块中,它们作为属性可被访问。

可编程式的按需导入

如果想基于某些条件或等某个事件发生后再加载需要的模块,可通过使用加载模块的可编程API(programmatic API)来实现。使用System.import方法,可按程序设定加载模块。这是一个异步的方法,并返回Promise。

该方法的语法示例如下:

System.import('./module1.js')    .then(function(module1){        //use module1    }, function(e){        //handle error    });

如果模块加载成功且将导出的模块成功传递给回调函数,Promise将会通过。如果模块名称有误或由于网络延迟等原因导致模块加载失败,Promise将会失败。

ES6模块使用现状

到目前为止,所有浏览器还不能自然支持ES6模块,所以在浏览器加载之前,我们需要使用转译器(transpiler)将代码转换成ES5。直到现在,我一直使用Traceur作为我的转译器,建议大家使用相同的工具将模块代码转化为浏览器可识别的代码。让我们看看编译ES6模块的几种不同的方法。

使用Traceur动态编译ES6模块

当浏览器加载脚本后,我们可以使用Traceur的客户端库动态编译ES6模块。使用该方法,运行模块无需运行任何命令。我们要做得就是,在页面上加载Traceur库,及添加代码脚本来运行WebPageTranscoder。

<script>    new traceur.WebPageTranscoder(document.location.href).run();</script>

现在,我们就可以在script标签内,将类型指定成模块,以此导入任何一个ES6文件。

<script type="module">    import './modules/import1.js';</script>

类型指定为模块的任何脚本标签将被ES6客户端库获取并处理。上面代码块中的导入语句将发送AJAX请求,捕获相应的JavaScript文件,并载入它。如果模块内部引用了另一个模块,单独的AJAX请求将发出,以加载与引用模块相对应的文件。

使用Traceur命令编译ES6模块

使用Traceur命令可以将ES6模块编译成AMD或者CommonJS模块。这个方法有两大优点。

  1. 模块完成编译,浏览器不必执行额外动作;
  2. 如果应用已经使用ES5及AMD(或CommonJs)模块系统构建了一半,程序的另一半也可以使用ES6,并被编译为这些模块系统中的任何一个,而不是立即把整个应用编译成ES6。

为了使用编译完成的AMD/CommonJs的模块,我们需要包含支持模块系统的库。我个人比较倾向AMD,所以我将在这里介绍一下它。CommonJS模块的步骤和这个差不多。

下面这句命令是用来让包含ES6模块的文件夹编译成AMD,并把它们存储在一个单独的文件夹:

traceur --dir modules es5Modules --modules=amd

使用CommonJs,你需要在上面命令中使用commonjs代替modules。

在这里,modules指的是包含ES6的文件夹,es5Modules指的是输出目录。如果查看es5Modules文件夹下的任何文件,你将看到该AMD定义块。require.js支持AMD,所以我们可以在HTML页面中,使用script引入require.js,并用data-main属性指明开始文件,就像下面这样:

<script src="bower_components/requirejs/require.js" data-main="es5Modules/import2.js"></script>

使用Traceur Grunt Task编译ES6模块

使用命令编译模块很累而且更容易出错。我们可以使用grunt-traceur自动化编译过程。此时,你需要安装NPM包。

npm intall grunt-traceur –save

Grunt任务所需数据与提供给命令的数据一样。下面是任务的一些配置:

traceur: {  options: {    modules: "amd"  },  custom: {    files: [{      expand: true,      cwd: 'modules',      src: ['*.js'],      dest: 'es5Modules'    }]  }}

现在你可以在控制台里使用下面的命令来运行上面的Grunt任务:

grunt traceur

正如你所看见的那样,它和我们使用命令所产生的效果是一样的。

结论

任何一个大型应用中,模块化十分必要。ES6模块为JavaScript提供了该特性,这些模块提供了众多选择来导出和引入对象。我很期待该特性被浏览器支持的那一天,到时我们无需加载任何第三方库即可创建、加载JavaScript模块。目前流行的客户端MV*框架Angular.js在其2.0版本(目前还在开发中)中就使用了ES6的模块化。

让我们开始使用模块系统,从而让我们的代码更具组织和可读性。(编译:肖元州,审校:陈秋歌)

原文链接:Modules in ECMAScript 6 (ES6)

一周热点:如何使用15美元每月的机器实现百万文档检索 黑客获取数据信息的目的和进攻手段及应对之策 Surface Pro 3遭大曝光:799$起、四色可选、12寸屏幕 当软件遇上设计,浅谈敏捷UX VS.精益UX DIY“物联网”——自己动手处理传感器数据 AMD成首家X86+ARM双架构计算 欲寻新蓝海 锤子手机发布:Smartisan T1与其背后的开发团队 第六届中国云计算大会在北京隆重举行 替代笔记本的Surface Pro 3:800g、9.1mm,极致轻薄 PWorld2014:畅谈企业软件向“大平台”+“微应用”变革 微软公司全球资深副总裁张亚勤:云计算引领互联网物理化 亚马逊网络服务全球市场副总裁Ariel Kelman:亚马逊AWS云服务推动创新 终超苹果,谷歌成全球最有价值品牌 高通业务拓展总监沈周全:以软件为基础建立差异化优势 设计你所需要的,而不是你想要的 疯狂谷歌建广告天网:电冰箱、汽车仪表盘、恒温器、眼镜和手表 开发者眼中的编程语言…… 寻下一突破口?黑莓推Project Ion项目,正式进军物联网 无人驾驶汽车真的要来了:飞思卡尔研制视觉芯片 支持物联网开发! Qt发布5.3版与嵌入式企业版 5月23日:Java已经19岁啦! Google发布Dart1.4版本,新增Observatory工具 《近匠》Mixtile:跑在盒子中的嵌入式平台 从研发、平台化到营销:移动时代,汽车厂商如何升级? CTO俱乐部“云计算创新与实践”沙龙:云计算的发展趋势与那些“坑” 一周消息树:大型网站系统与Java中间件 良心推荐:6款基于云的移动应用开发工具 Google Project Tango第二弹:可生成3D图像的平板电脑 API企业化战略部署三部曲(一) 高通产品市场经理刘晓光:详解骁龙Android SDK 苹果史上最大交易:斥资30亿美元收购Beats 问一个简单的概念性问题,分却很多.......还可加哦 哪里可以找到关于OA方面的资料?越多越好,100分送上 高手请进,怎么监测到一个文件将被覆盖 请问如何屏蔽F1查看帮助的功能? 高手请进,怎么监测到一个文件将被覆盖 能提供解码器么? 在tdi中,怎样获取封包ip头? 神啊!救救我吧!!!!(在线等待) 我看SARS危机 求助 我该怎么办??? 管理登陆问题解决?? 一个简单的问题,如何对字符串进行减操作? 谁用过struts,进来交流一下! 请大侠看看俺的小程序,哪里错了(关于不规则图形填充) delphi查询问题(急需) 急求:从硬盘安装windowsxp时电脑出显不能安装,找不到eula!如何解决? 系统分析员VS博士 C#连接Oracle? 关于<BASE> 那里有WebDB下载啊. 在ListCtrl里加类似Combo Box的东西,能实现吗? windows2000下vb的一个小问题~~ 如何把当前路径加入查找路径中?立即给分! 对选用不同的纸张大小,在预览中能看出效果吗? 请问怎么在PB6.0中实现Foxpro(*.dbf)的数据导入,到ASA库中 j2me里怎么才能实现图象的滤镜效果?waiting... CDbSet m_dbSet(NULL)在哪一步才能得到一个CDatabase对象的错针? 新手提问:“镜象”是什么意思 求教,如何配置使性能达到最佳,详情见文 怎样在广域网中提高传屏响应速度?帮帮忙!急啊. 在文件钩子当中如何判断是打开文件操作,还是创建文件操作 怎样在applet程序中显示一幅jpeg图片?该图片存在于c:\image\下。 去年12月是谁发的帖子“做项目经理难么” 关于图层拖拽的问题 我有一块硬盘,迈托4.3G,开格式化分时说错误设备或0磁道损坏,后来fdisk分区,启动无效 这是个什么错误啊~ 第一次做控件不明白 给点指点啊 急求:从硬盘安装windowsxp时电脑出显不能安装,找不到eula!如何解决? 不用的控件怎样从工程中删除? 怎样将一个表中的全部数据追加到别一个表的后面????在线 我做软件这些年 求scjd的模拟题 为什么我连续给一个socket send三次,socket一次就接收完了? 关于HTML代码不区分大小写? 大家看一下这个CListCtrl是啥回事?? Turbo c++3.0怎么使用? 《水园MSN俱乐部宗旨》 ODBC连接数据库的一个问题求教 如何让网页一打开就是全屏模式? 关于打印的问题 怎么彻底卸载linux啊!放分100 原电池 【化学高手进】如图所示的装置中,在产生电流时,以下说法不正确的是A.Fe是负极,C是正极B.负极反应式为:Fe-3e-=Fe3+C.内电路中阴离子移向FeCl2溶液D.电流由石墨电极流向Fe电 做实验时虹吸管提前发生虹吸现象该怎么办? 产业组织结构、产业间及产业内部结构个指的是什么?有什么区别? 臭氧、黄铜、水三者一起会发生什么反应?即臭氧通入水中,含臭氧的水流过黄铜水管,结果如何?黄铜在水中遇到某些氧化剂,氧化是肯定的.听说铜、锌、水三者之间会产生一种电介质,并加速腐 为什么浓硫酸能作为酯水解的催化剂阿,它不是会吸水吗,反应不就像逆反应方向生成酯了吗?那都可以用碱干吗还用稀硫酸阿?在说了 我们在写酯化反应时 用的箭头是双箭头,条件是浓硫酸,你 如何在墙上写字(打广告)?毛笔,墨水不行写一下蘸一下太麻烦,请给点建议吧 能否说质子酸都是Lewis酸? 罗马斗兽场是用什么石头建成的?雕塑呢? 得了芥子怎么办 CH5+为什么是质子酸而不是Lewis酸 07年化学竞赛初赛有一道题大致意思就是这个但我读到的书说 所有布朗斯特酸都是Lewis酸 使我产生了迷惑CH5+为什么是质子酸而不是Lewis酸 离子方程式为Zn+2H+ =Zn2+ +H2.可以设计成电解池和原电池 那么电离子方程式为Zn+2H+ =Zn2+ +H2.可以设计成电解池和原电池 那么电极可不可能是同种材料?比如呢., 如何看到紫外线 HF是质子酸,但是F有孤对电子,可以做lewis碱吗? 一直某池(原电池或电解池)的总反应离子方程式是Fe+2H*=Fe*+H2 该池是什么池如果是原电池,为是那么不能是电解池 电磁炉维修串联60瓦灯泡后开机检锅正常,放上锅后灯泡猛亮一下熄灭,便自动关机,重复上述还是一样曾经换过一次IGBT,重新更换了LM339,及驱动管S8550 S8050 有18V 5V 285V电压,各大电容也换过了,还 请问这句深奥的话是什么意思?咸菜虽不是主菜,却容易下饭!但咸菜总归是咸菜,别一时糊涂当成了主菜!暗示着什么含义? 右图装置中发生反应的离子方程式为zn+2h 混合物质中怎样萃取我们所需要的部分? 什么石头可以雕刻石像 居民楼燃气爆炸谁承担后果 PH试纸上滴入NAcl,试纸变什么颜色 这些深奥的话究竟是什么意思呢?人生若都是喜剧,那就不叫人生了.我们不需要眼泪,如果欣赏艺术也要欣赏悲剧的话,那就欣赏自己的人生算了.成熟也是一种人生. 小苏打能不能除去自来水中的氯离子?我家养的乌龟一直用自来水,最近好象生病了,可能是自来水的缘故,我想用大苏打除去水中的氯离子可是没买到,只有小苏打不知道小苏打有什么用,是不是 3/8"NPT FEMALE-FEMALE PIPE COUPING. 毕竟西湖六月中,下句是什么 用小苏打去除自来水的氯比列应是多少?百度上不是都说小苏打也能除氯吗? 四氟化四硼的空间构型 毕竟西湖六月中的意思意思!快,最好是简洁的,不要其他,只要意思 《快乐酷宝》里哪台天文望远镜更好用? 判断四氟化硫(SF4)的分子空间构型?用VSEPR法判断四氟化硫(SF4)的分子空间构型时,LP不等于0,孤对电子位置有两种情况,用斥力最小原理怎么确定 “神经递质与受体结合后,突触后膜产生兴奋.”这句话错哪了? 《快乐酷宝》里的天文望远镜耐用吗? 灯泡L1“3v,3w”灯泡L2“3v,6w”并联在1.5v电源上,那个灯泡亮 神经递质通过受体进入突触后膜,是什么跨膜运输方式 《快乐酷宝》里的天文望远镜,属于哪个品牌的? 灯泡给名牌比较哪个更亮这种题怎么算 L1“6v 6w” L2“3V 3W”并联在某电源上 哪个灯更亮,实际功率之比 2000名儿童参加爬山,海底世界和当秋千三项目,规定每人要参加两项目.至少有多少人参加的活动项目相同 某厂漂白车间需22.4LSO2,化学兴趣小组同学依据化学方程式:Zn+2H2SO4(浓)=(加热)ZnSO4+SO2+2H2O计算后,`取65g锌粒与98%的浓硫酸(P=1.84g/cm^3)110ml,充分反应,锌全部溶解后,即将收集所得气体如数送至车间 试药有危险吗? 非零和对策的特点有哪些? 地下水污染会对农业种植产生危害吗? dna羟基末端怎么念,3’端念什么?5‘端念什么? 请问有没有不带脏字的骂人的话?深奥的,傻子听不懂的那种.有个猪婆一见就打我骂我!还说些骂人的话. 《快乐酷宝》里的天文望远镜很不错,请问是国产品牌吗? 现在北京还有试药的吗? 一些关于什么的深奥的话!就是要那种的话像:叶子的离去,是因为风的追求,还是树的不挽留?就要类似这样的,用物喻人,要经典的,在要些教育人的话,不要太长的, ZN+2H2SO4=ZNSO4+SO2+2H2O 反应一段时间后还会生成什么气体 DNA羟基端是哪个,我怎么觉得是B在遗传病及刑侦破案中常需要对样品DNA进行分析,PCR技术能快速扩增DNA片段,在几个小时内复制出上百万份的DNA拷贝,有效地解决了因为样品中DNA含量太低而难以 深奥点的话别人看不起我 谁给我想一句话要深奥的那种做我座右铭!努力奋斗!让曾经那些看不起我的人刮目相看 《快乐酷宝》里上官绮罗用的天文望远镜哪里有卖? DNA或RNA中的磷酸含有几个羟基,为什么? 深奥的话帮忙写些关于儿童的青年也可以- - Zn+H2SO4==ZnSO4+H2(气体符号比如Zn 有13g 即0.2mol 那么H2SO4是xmol 就是正好跟它反应的xmol 那么x=0.是=0.2吧. 这句话怎么理解,3'端不就是DNA的头吗,(含有羟基) 水处理后的浓盐水可以用磷酸三钠处理防止水垢生成么水师由水处理车间处理后的浓盐水,我们用来冲渣,但存在结垢问题,是否可以用磷酸三钠处理? 怎样制取znso4? 端羟基聚丁二烯的红外谱图及其分析? 橡胶模具O型圈板模哪里开得好,错模量,型腔尺寸一致性,型腔表面粗糙度这些质量都非常好,各位帮推荐一个 Zn经过化学变化得到ZnSO4是得电子还是失电子 共发射极放大器中,集电极电阻的作用是什么 支付宝鼓励用户提前充值:余额宝不会出基金淘宝店出师不利 交易量日益走低苹果语音助理Siri配音员现身港版iPhone 5s/5c可用中国亚洲邮轮旅游市场增长迅速美国新泽西一商场发生枪击事件 暂无人三中全会前瞻:改革力度超以往 让民众网曝湛江国资委官员带女下属开房 视频广东湛江国资委官员被曝与女下属开房 韩媒称韩国海警截获三艘“非法捕捞”中塑料袋威胁欧洲环境 欧盟计划对其征收澳华裔女专家制乳癌病例数据库 拯救数美国新泽西一商场发生枪击事件 暂无人曝孙杨因同乘者不满赔偿金才报警 托人美国国务卿克里访波兰 有望就监听事件穆尔西受审质疑审判合法性 埃及民众意发改委:雾霾天气几乎常态化 通过5-雾霾影响生殖能力,不能当成“雷语”加拿大一名刑满性犯罪者潜逃至美国又面日本一企业官员疑挪用24亿日元 被同消息称利比亚首都发生激烈交火 枪声持百程大手笔促销,差异化商品助力出境游淄博:别再贪小便宜了!网络“秒杀”当春运抢票迎来高峰 QQ浏览器抢票免单淄博供电公司 发明出巡视工作抗霾神器淄博:“五个强化”筑外包施工安全防线8个月自驾6万公里边境线 这事儿能炫凯度零售咨询发布《2016年中国快速【有人@你】听说会玩的人都下载了这款携程旅行顾问:全国明星海选,正式拉开倒计时3天|莫奈展即将离去优软科技:电商3.0,云商时代已来临狂欢继续,迪信通23周年庆购物盛宴重济宁市纪委通报违反中央八项规定精神的热烈祝贺恒泰证券荣获2016杰出营销天威诚信助力消费金融发展大会共商法律枣庄: 车站旅客遗忘贵重物品 工作人蜘点综合仓合伙人全国招募启动深商大会到底有多吸睛?华大基因汪建说淄博好人好事!老人突发病民警伸援手2016首届西部互联网农业大会在四川湖北黄石“收复”长江岸线 新港吞吐能
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘