学习笔记
es5模块化
优点 :
1.不需要配置环境,纯靠原生JS(闭包)支持
2.解决了全局变量污染和命名冲突
缺点 :
1.依赖script标签的加载顺序
2.扩展方式略显麻烦
写法 :
// module1.js
window['es5module'].m1 = (() => {
var name = 'JSmodule'
return {
name
}
})()
// module2.js
window['es5module'].m2 = (() => {
var int = 300
return {
int
}
})()
// module3.js
// 先定义一个模块盒子对象,用来存储后续模块
Object.defineProperties(globalThis, {
'es5module': {
value: {} // 给window加个变量用来给扩展后续模块
}
})
window['es5module'].m3 = ((m1, m2) => {
var say = function () {
return `我的名字是${m1['name']},我有${m2['int']}块钱`
}
return {
say
}
// 引入依赖模块,其实就是给立即执行函数传winodw里面变量的参数
})(window['es5module'].m1, window['es5module'].m2)
PS:立即执行函数有函数作用域,变量在里面定义只会在该函数内有效,不会提升到全局,同时return该变量会保持变量的引用,这样就不会触发JS引擎的垃圾回收机制啦
commonJS
优点 :
1.是nodeJS的模块规范
2.解决了加载顺序问题
3.一次加载即缓存模块,解决多次加载照成的资源浪费
4.模块作用域,模块内变量不会影响到全局
缺点 :
1.运行代码时才会加载
2.require(xxx)输出的值是浅拷贝值
3.无法直接在客户端使用,需要借助nodeJS环境和webpack
4.同步执行(在nodeJS环境没什么影响),但如果在客户端运行就会很吃网速
写法 :
// common1.js
var a = (() => {
return ['js++module']
})()
module.exports = {
a
}
// common2.js
var { a } = require('./commonjs1')
var b = (() => {
var _b = [0xff, 0x11, 0x22, 0x33]
return _b.concat(a)
})()
module.exports = {
b
}
// common3.js //中需引入common3.js文件,require会自动帮我们找到依赖模块
var { b } = require('./commonjs2')
var { a } = require('./commonjs1')
var c = (() => {
return {
c: b.concat([10, 20, 30, 40]),
log: function () {
console.log(a, b)
}
}
})()
Object.defineProperty(globalThis, 'common', {
value: {
a,
b,
c
}
})
PS:模块的加载实质上就是,注入exports、require、module三个全局变量,然后执行模块的源码,然后将模块的 exports 变量的值输出。
AMD ‘Asynchronous Module Definition’
优点 :
1.异步方法加载模块,可以不借助nodejs实现在客户端运行,适合在浏览器用
2.所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
缺点 :
1.写法不太妙
2.仍然需要进行一些配置才能使用
写法 :
define('moduleA', function () {
var a = [1, 2, 3, 4, 5]
return {
a
}
})
require([module], callback);
PS:目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js
CMD ’Common Module Definition’
优点 :
1.阿里巴巴出的
2.CMD是依赖就近,延迟执行,只有在用到某个模块的时候再去require,而AMD是依赖前置,提前执行
3.也是异步加载模块
缺点 : 不了解
写法 :不了解
PS:基于在 Sea.js,感兴趣的可以去看看
es6module
优点 :
1.是ECMA规范,语言层面实现模块化,nodeJS也可以用
2.输出的值是值引用
3.编译时执行
4.写法简单
5.也有缓存机制
缺点 :
1.老浏览器不支持
写法 :
// e6m1.js
export const name = '梅'
export function log() {
console.log(arguments)
}
// export default就是没名字的导出
export default class {
say() {
console.log('你是好人')
}
}
// e6m2.js
// 命名导出,import关键字会被提升
import { name as bar, log } from './es6module1'
// 全部导出再重命名
import * as m1 from './es6module1'
// 默认导出
import Hello from './es6module1'
// 还有个 import()写法,返回promise,可以自己去尝试
console.log(bar, log)
console.log(m1)
console.log(Hello)
四种模块导出方式的区别
-
module.exports:nodeJs的默认导出,exports引用该变量。
-
exports:引用module.exports,如果将该变量直接赋值为其他值,不会影响module.exports默认导出
-
export default:发现是修改module.exports里面的default值.
但并不全等于直接赋值default,export default导出可以直接在另一个文件import xxx from 'xxx',但直接赋值就会导致报错.
-
export:与exports.xxx几乎一致