ES6深入浅出 模块系统
一步,一步前進の一步。
模块化主要是帮助我们更好的组织代码,模块允许我们将相关的变量和函数放在一个模块中。在 ES6 模块化之前,JS 语言并没有模块的概念,只有函数作用域和全局作用域非常容易发生命名冲突。之前的 RequireJS
、SeaJS
、AMD
、UMD
、CMD
啥的,在一定层面上都是为了解决 JS 模块化的问题。
笔者是一个也不会用啊(技术发展太快了,新技术学不过来,还是坐等它们过时吧,果然 webpack 和 es6替代了它们),一步心中有个期待,啥时候我们用的 ES6、ES7直接运行在浏览器上吧,我现在还坐等 webpack 和 babel 死掉呢,一点还不会呢。
什么是模块
模块是自动运行在严格模式
下的JS 代码,在模块中创建的变量不会被添加到全局共享作用域,这个变量只会存在于模块的作用域
中,在模块中 this的值是 undefined
。模块的真正魔力所在是仅导入
、导出
你需要的绑定,而不是将所用的东西都放在一个地方。一个文件即一个模块。
严格模式
模块中的代码是在严格模式下运行的,等同于在文件的顶部use strict
。JS 在严格模式下使用会更加的严谨。简单列举几条严格模式的规则:
变量使用前必须声明
函数不能有重名参数
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
这样做的好处如下:
模块中导出的部分变得显而意见,不需要从头到尾去找模块中哪里是私有的,哪里是需要export 出去的,只需要滚动到文件底部就可以一目了然。
不用纠结是应该使用命名导出,列表导出,还是重命名导出了,只使用
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的模块是如何加载的,只知道打包工具帮我们处理好了,实际上我们并不了解模块化的知识。有时间再更新。
。。。。
共同学习,写下你的评论
评论加载中...
作者其他优质文章