继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

ES6深入浅出 模块系统

繁星点点滴滴
关注TA
已关注
手记 335
粉丝 67
获赞 333
一步,一步前進の一步。

模块化主要是帮助我们更好的组织代码,模块允许我们将相关的变量和函数放在一个模块中。在 ES6 模块化之前,JS 语言并没有模块的概念,只有函数作用域和全局作用域非常容易发生命名冲突。之前的 RequireJSSeaJSAMDUMDCMD啥的,在一定层面上都是为了解决 JS 模块化的问题。

笔者是一个也不会用啊(技术发展太快了,新技术学不过来,还是坐等它们过时吧,果然 webpack 和 es6替代了它们),一步心中有个期待,啥时候我们用的 ES6、ES7直接运行在浏览器上吧,我现在还坐等 webpack 和 babel 死掉呢,一点还不会呢。

什么是模块

模块是自动运行在严格模式下的JS 代码,在模块中创建的变量不会被添加到全局共享作用域,这个变量只会存在于模块的作用域中,在模块中 this的值是 undefined。模块的真正魔力所在是仅导入导出你需要的绑定,而不是将所用的东西都放在一个地方。一个文件即一个模块。

严格模式

模块中的代码是在严格模式下运行的,等同于在文件的顶部use strict。JS 在严格模式下使用会更加的严谨。简单列举几条严格模式的规则:

  1. 变量使用前必须声明

  2. 函数不能有重名参数

  3. with 不允许使用

。。。
更多规则请参考阮一峰老师的文章严格模式

export

在 ES6模块中的声明的作用范围就被限定在了模块文件中,文件外部是无法访问的,必须使用 export关键字将引用显示的暴露出去。

默认导出

可以使用 export default进行默认导出,注意一个模块中只可以有一个默认导出。

export default 1 export default NaN export default 'foo' export default { foo: 'bar' } export default ['foo', 'bar']

命名导出

命名导出和默认导出同样常用,如果一个模块想要导出多个声明时较为常用,使用如下:

export var foo = 'bar' export var baz = 'ponyfoo'

导出是绑定

需要注意的是 ES6模块导出的是绑定关联,不是值的复制,意味着如果你导出一个变量 foo,那么 foo 是和模块内部是相互关联连动的,我个人反对去更改一个模块所暴露出来的接口(export出来的部分)。

假设你有个模块./a,导出的 foo 变量初始值是 bar 将在500ms 变成 baz,在使用该变量的地方(import处)也会有该变化。

export var foo = 'bar' setTimeout(() => foo = 'baz', 500)

导出列表

ES6 的模块允许你导出一个命名导出列表,代码片段如下:

var foo = 'ponyfoo' var bar = 'baz' export { foo, bar }

同时可以对命名导出进行重命名:

export { foo as ponyfoo }

导出的最佳实践

我们学会了命名导出导出列表默认导出导出重命名,此时你应该有点疑惑,我该选择那种方式实现自己的导出呢?人呐之所以烦恼,就是因为选择太多了。作者推荐大家在文件的尾部使用export default进行默认导出。

var foo = 'ponyfoo' var bar = 'baz' ... var api = {   foo,   baz,   ... } export default api

这样做的好处如下:

  1. 模块中导出的部分变得显而意见,不需要从头到尾去找模块中哪里是私有的,哪里是需要export 出去的,只需要滚动到文件底部就可以一目了然。

  2. 不用纠结是应该使用命名导出,列表导出,还是重命名导出了,只使用export default不知道大家有没有注意到,当你将一个对象作为默认导出接口时,即可以结合命名导出,还可以重命名,还能支持导出多个。

import

import 关键字的作用和 export 的作用正好相反,import 的作用是当年想使用其他模块中的内容时进行关系绑定。

导入默认导出

当想在另一个模块中使用上一个模块的默认导出时十分方便,impprt 后面的名字可以随便起,代码如下:

import _ from 'lodash' import lodash from 'lodash'

导入命名导出

import关键字后面使用花括号包上你想要使用的命名导出。

import {map, reduce} from 'lodash'

导入时也可以进行重命名

import {cloneDeep as clone, map} from 'lodash'

完全导入一个模块

import * as _ from 'lodash' //使用时采用_.的形式 _.map()

无绑定的导入

有些模块也许没有进行任何导出,相反只是修改全局作用域的对象。尽管这种模块的顶级变 量、函数或类最终并不会自动被加入全局作用域,但这并不意味着该模块无法访问全局作用 域。

加载模块

虽然我们日常编码中在使用 ES6的 import和 export 关键字,但是仔细想一下,我们并不了解 ES6的模块是如何加载的,只知道打包工具帮我们处理好了,实际上我们并不了解模块化的知识。有时间再更新。
。。。。

原文ES6 Modules in Depth


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP