工程化(一)之模块化规范
Opened this issue · 1 comments
adodo0829 commented
传统模式下的模块
- 函数即模块
<script>
function module() {
// doSomething
}
</script>
<!-- 利用全局变量, 即模块依赖不清晰 -->
- 对象即模块
<script>
var module = {
id: 0,
say: function () {}
}
</script>
<!-- 也是全局变量对象, 且成员属性会被修改 -->
- 自执行函数(函数作用域实现私有成员)
<script>
var module = (function() {
var id = 0; // 私有变量
var hello = function () {};
var world = function () {};
return {
hello: hello,
world: world
}
})();
</script>
<!-- 全局变量, 但实现了部分成员私有, 其他成员共享 -->
<script>
module.hello()
module.world()
</script>
CommonJS 规范
node 环境下每个文件都有自己的模块作用域, 变量都属于模块
- 导出模块
// 1.整体内容导出
// module.exports 初始值为一个空对象 {}, 由 Module 系统创建
module.exports = {
id: 1,
say: () => {}
}
// 2.exports导出
// exports 也是一个模块下的变量, 指向module.exports的引用, 指向同一块内存
exports.id = 1
exports.say = () => {}
// 模块导出的始终是 module.exports 对象
exports = module.exports = { id: 2, say: () => {} }
- 导入模块
// node 下全局方法 require
var module1 = require('./module1.js') // 导入本地文件模块, 相对路径查找
var path = require('path') // Node自带的模块, 得出相对路径后查找
var lodash = require('lodash') // node_modules目录下的模块, 通过文件名逐级往上查找
- 模块加载特点
1.所有代码都运行在模块作用域,不会污染全局作用域
2.模块是同步加载的,即只有加载完成,才能执行后面的操作
3.模块在首次执行后就会缓存,再次加载只返回缓存结果,如果想要再次执行,可清除缓存
4.模块加载的是值的拷贝, 同时 require('./moudle.js') 多次都只是一个对象的拷贝;
CommonJS 模块遇到循环加载时,返回的是当前已经执行的部分的值,而不是代码全部执行后的值
AMD 规范(require.js)
异步加载
浏览器环境下使用
定义模块: define(fn())
导入: require(['模块名',...], cb())
存在缓存
ESModule 规范
js 语言环境下使用, 语言层面的规范;
需要 babel工具 进行语法编译
export: 规定模块对外接口
默认导出:export default Person(当导入时可指定模块任意名称,无需知晓内部真实名称)
单独导出:export const name = "huhua"
按需导出:export { age, name, sex }(推荐)
改名导出:export { name as newName }
import:导入模块内部功能
输入的模块变量是不可重新赋值的,它只是个可读引用,可以改写属性
默认导入:import Person from "person"
整体导入:import * as Person from "person" // Module对象
按需导入:import { age, name, sex } from "person"
改名导入:import { name as newName } from "person"
自执导入:import "./person"
复合导入:import Person, { name } from "person"
复合模式
当export命令和import命令
结合在一起写成一行,变量实质没有被导入当前模块,相当于对外转发接口,导致当前模块无法直接使用其导入变量
默认导入导出:export { default } from "person"
整体导入导出:export * from "person"
按需导入导出:export { age, name, sex } from "person"
改名导入导出:export { name as newName } from "person"
具名改默认导入导出:export { name as default } from "person"
默认改具名导入导出:export { default as name } from "person"
CommonJS与ESModule规范的区别
-
CommonJS模块是运行时加载,ES6 Modules是编译时输出接口
CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。
而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成 -
CommonJS输出是值的拷贝; ES6 Modules输出的是值的引用,被输出模块的内部的改变会影响引用的改变
-
CommonJs导入的模块路径可以是一个表达式,因为它使用的是require()方法;而ES6 Modules只能是字符串
-
CommonJS this指向当前模块,ES6 Modules this指向undefined
ES6 Modules中没有这些顶层变量:arguments、require、module、exports、__filename、__dirname
webpack打包工具
为了让同一套代码在各个运行环境规范下都能适用
- 模块解析
将各个模块维护到一个list中
/* module code */ 样板代码解析 replace
- 模块加载
同步加载: 直接加载文件
异步加载: jsonp + promise
adodo0829 commented
update: module