概况
项目变大时需要把不同的业务分割成多个文件,这就是模块的思想。模块是比对象与函数更大的单元,使用模块组织程序便于维护与扩展。
在ES6之前,JavaScript一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。这对开发大型的、复杂的项目形成了障碍。
为了解决这个问题,创造了一些模块加载方案(如用于服务器的CommonJS,用于浏览器的AMD、CMD),各个方案各有自己的特点,并且语法还不一样,如果是要同时做前后端,那真的是会“精分”了。
好消息是ES6给我们带来了模块化的设计!这完全可以取代CommonJS、AMD等规范,成为浏览器和服务器通用的模块解决方案。
模块功能主要由两个命令构成:export 和 import。export 命令用于规定模块的对外接口,import 命令用于输入其他模块提供的功能。
下面通过定义一个类似 require.js 的 AMD 模块管理引擎,来体验模块的工作原理。
<script>
let module = function() {
// 模块列表集合
let moduleLists = {};
function define(name, modules, action) {
modules.map((m, i) => {
modules[i] = moduleLists[m];
});
moduleLists[name] = action.apply(null, modules);
}
return { define , moduleLists };
}();
module.define("show",[],function(){
return {
show() {
console.log('show module')
}
}
})
module.define('myMath',[],function(){
return {
Max(arr, key) {
return arr.sort((a, b) => b[key] - a[key])[0]
}
}
})
module.define('xj',['show'],function(show){
show.show()
})
module.define('compute',['myMath'],function(myMath){
let data = [
{name:'js', price:180},
{name:'css', price:60}
];
console.log(myMath.Max(data,'price'))
})
</script> 常见问题
模块01.js开放了title,那么在其他模块中就可以使用title了,url是使用不了的
但是存在一个问题是如果你像下面这样写的话浏览器是会报错的
报错如下:
因为受到浏览器加载规则的限制,浏览器加载ES6模块,也是使用标签,但注意,需要加上 type="module" 属性。
可以有两种方法
1. 通过<script src="">加载js脚本
2.直接使用<script>标签内嵌js代码
这并不是Chrome不支持加载模块,而是ES6模块遵循同源策略。解决方法就是打开本地服务器,让各个文件同源就可以了。
解决方法:
在本地使用node建立一个服务器
let path = require('path')
let express = require('express')
var app = express()
app.use(express.static(path.join(__dirname,'./')))
app.listen(8080, () => {
console.log(`App listening at port 8080`)
})
在Chrome浏览器地址栏中输入对应的地址就可以正确访问了,因为两个文件处于一个服务器,浏览器就不会报非同源限制的错误
接着就可以在浏览器控制台上看到打印的结果了
模块的延迟解析
一般情况下解析的顺序是从上到下,但是在模块中不同
模块总是会在所有html解析后才执行,下面的模块代码可以看到后加载的 button 按钮元素。
建议为用户提供加载动画提示,当模块运行时再去掉动画
<body>
<script type="module">
console.log(document.querySelector("button")); //Button
</script>
<script>
console.log(document.querySelector("button")); //undefined
</script>
<button>按钮</button>
</body> 模块默认运行在严格模式下
如果模块里面书写的不是严格模式会报错模块作用域
模块都有独立的顶级作用域,不同模块之间不能互相访问
<script type="module"> let hd = " niuke.com"; </script> <script type="module"> alert(niuke); // Error </script>
模块的预解析
模块在导入时只执行一次解析,之后的导入使用第一次解析结果,并共享数据。

京公网安备 11010502036488号