js 模块化基础和模块规范AMD、CMD、ES6模块
一、模块基础
1、基于文件的模块化
把相关函数写在一个文件里
<script>
function func1() { // ...
} function func2() { // ...
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
缺点:污染了全局变量,无法保证不与其他模块发生变量名冲突
2、基于对象的模块化
把所有的模块成员封装在一个对象中
<script>
var myModule = { name: "Tom", func: function () {},
};
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
优点:避免了变量污染,只要保证模块名唯一即可
缺陷:外部可以随意修改内部成员
3、基于函数的模块化
通过立即执行函数返回对象
<script>
var myModule = (function () { var name = "Tom"; function func() {} return { name: name, sayHello: sayHello, };
})();
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
优点:模块外部无法修改我们没有暴露出来的变量、函数
二、JavaScript 模块规范
其中【基于函数的模块化】是模块化的基础
目前,通行的 JavaScript 模块规范主要有两种:CommonJS 和 AMD
1、Node.js 实现 CommonJS
- 定义模块:一个文件就是一个模块,有单独的作用域
- 模块输出:要导出的内容放入 module.exports 对象
- 加载模块:require 返回 module.exports 对象
eg:
定义模块
// a.js
function func() {
console.log("func");
}
module.exports = {
func: func,
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
加载模块
// b.js
const myModule = require("./a");
myModule.func();
- 1
- 2
- 3
- 4
- 5
以上方法浏览器不直接支持
2、AMD 异步模块定义
Asynchronous Module Definition
由 require.js 支持
实现接口:
// 定义模块
define(id?, dependencies?, factory);
id:模块的标识,默认脚本文件名
dependencies:当前模块依赖的模块名称数组
factory:模块初始化要执行的函数或对象
// 加载模块
require(dependencies, callback);
dependencies: 所依赖的模块数组
callback: 前面指定的模块都加载成功后的回调函数
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
eg:
1、下载
wget https://cdn.bootcdn.net/ajax/libs/require.js/2.3.6/require.min.js
- 1
2、helper.js 定义模块
// 模块名,模块依赖,模块的实现function
define(function () {
return { func: function () { console.log("hello"); },
};
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2、app.js 引入模块
require(["helper"], function (helper) {
helper.func();
});
- 1
- 2
- 3
3、index.html 浏览器中使用
<script src="require.min.js" data-main="app.js"></script>
- 1
3、CMD 通用模块定义
Common Module Definition
由 Sea.js 支持
文档:https://seajs.github.io/seajs/docs/#intro
实现接口
// 定义模块
define(id?, deps?, factory)
一般不在define的参数中写依赖
factory = function(require, exports, module)
require 用来获取其他模块提供的接口:require(id)
exports 用来向外提供模块接口
module 存储了与当前模块相关联的一些属性和方法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
eg:
1、下载
wget https://cdn.bootcdn.net/ajax/libs/seajs/3.0.3/sea.js
- 1
2、helper.js 定义模块
define(function (require, exports, module) {
exports.func = function () { console.log("hello");
};
});
- 1
- 2
- 3
- 4
- 5
3、app.js 引入模块
define(function (require, exports, module) {
var helper = require("helper");
helper.func();
});
- 1
- 2
- 3
- 4
4、index.html 浏览器中使用
<script src="sea.js"></script>
<script>
seajs.use("app");
</script>
- 1
- 2
- 3
- 4
- 5
4、AMD 与 CMD 区别
- AMD 推崇依赖前置,在定义模块的时候就要声明其依赖的模块
- CMD 推崇就近依赖,只有在用到某个模块的时候再去 require
三、ES6 模块
1、ES6 模块与 CommonJS 模块的差异
差异点 | CommonJS | ES6 |
---|---|---|
模块输出 | 值拷贝 | 值引用 |
机制 | 运行时加载 | 编译时输出接口 |
顶层 this 指向 | 当前模块 | undefined |
以下这些顶层变量在 ES6 模块之中都是不存在的
arguments
require
module
exports
__filename
__dirname
- 1
- 2
- 3
- 4
- 5
- 6
2、模块加载
1、传统方法
<!-- 页面内嵌的脚本 -->
<script type="application/javascript">
// module code
</script>
<!-- 外部脚本 -->
<script type="application/javascript" src="demo.js"></script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
浏览器脚本的默认语言是 JavaScript,因此 type="application/javascript"
可以省略
默认情况下,浏览器是同步加载 JavaScript 脚本,执行完脚本,再继续向下渲染
2、异步加载脚本
<!-- 渲染完再执行 -->
<script src="demo.js" defer></script>
<!-- 下载完就执行 -->
<script src="demo.js" async></script>
- 1
- 2
- 3
- 4
- 5
3、ES6 加载
<script type="module" src="./foo.js"></script>
<!-- 等同于 -->
<script type="module" src="./foo.js" defer></script>
- 1
- 2
- 3
eg:
模块文件 demo.js
export default function () {
console.log("demo");
}
- 1
- 2
- 3
主文件 index.html
<script type="module">
import Demo from "./demo.js";
Demo();
</script>
- 1
- 2
- 3
- 4
参考
文章来源: pengshiyu.blog.csdn.net,作者:彭世瑜,版权归原作者所有,如需转载,请联系作者。
原文链接:pengshiyu.blog.csdn.net/article/details/106031080
- 点赞
- 收藏
- 关注作者
评论(0)