全局function模式 : 将不一样的功能封装成不一样的全局函数javascript
function m1(){
//...
}
function m2(){
//...
}
复制代码
namespace模式 : 简单对象封装css
let myModule = {
data: 'www.baidu.com',
foo() {
console.log(`foo() ${this.data}`)
},
bar() {
console.log(`bar() ${this.data}`)
}
}
myModule.data = 'other data' //能直接修改模块内部的数据
myModule.foo() // foo() other data
复制代码
这样的写法会暴露全部模块成员,内部状态能够被外部改写。html
IIFE模式:匿名函数自调用(闭包)前端
// index.html文件
<script type="text/javascript" src="module.js"></script>
<script type="text/javascript"> myModule.foo() myModule.bar() console.log(myModule.data) //undefined 不能访问模块内部数据 myModule.data = 'xxxx' //不是修改的模块内部的data myModule.foo() //没有改变 </script>
复制代码
// module.js文件
(function(window) {
let data = 'www.baidu.com'
//操做数据的函数
function foo() {
//用于暴露有函数
console.log(`foo() ${data}`)
}
function bar() {
//用于暴露有函数
console.log(`bar() ${data}`)
otherFun() //内部调用
}
function otherFun() {
//内部私有的函数
console.log('otherFun()')
}
//暴露行为
window.myModule = { foo, bar } //ES6写法
})(window)
复制代码
最后获得的结果:java
IIFE模式加强 : 引入依赖jquery
这就是现代模块实现的基石webpack
// module.js文件
(function(window, $) {
let data = 'www.baidu.com'
//操做数据的函数
function foo() {
//用于暴露有函数
console.log(`foo() ${data}`)
$('body').css('background', 'red')
}
function bar() {
//用于暴露有函数
console.log(`bar() ${data}`)
otherFun() //内部调用
}
function otherFun() {
//内部私有的函数
console.log('otherFun()')
}
//暴露行为
window.myModule = { foo, bar }
})(window, jQuery)
复制代码
// index.html文件
<!-- 引入的js必须有必定顺序 -->
<script type="text/javascript" src="jquery-1.10.1.js"></script>
<script type="text/javascript" src="module.js"></script>
<script type="text/javascript"> myModule.foo() </script>
复制代码
上例子经过jquery方法将页面的背景颜色改为红色,因此必须先引入jQuery库,就把这个库看成参数传入。这样作除了保证模块的独立性,还使得模块之间的依赖关系变得明显。web
首先咱们要依赖多个模块,那样就会发送多个请求,致使请求过多编程
咱们不知道他们的具体依赖关系是什么,也就是说很容易由于不了解他们之间的依赖关系致使加载前后顺序出错。浏览器
以上两种缘由就致使了很难维护,极可能出现牵一发而动全身的状况致使项目出现严重的问题。 模块化当然有多个好处,然而一个页面须要引入多个js文件,就会出现以上这些问题。而这些问题能够经过模块化规范来解决,下面介绍开发中最流行的commonjs, AMD, ES6, CMD规范。
1.CommonJS
2.AMD
定义暴露模块:
//定义没有依赖的模块
define(function(){
return 模块
})
复制代码
//定义有依赖的模块
define(['module1', 'module2'], function(m1, m2){
return 模块
})
复制代码
引入使用模块:
require(['module1', 'module2'], function(m1, m2){
使用m1/m2
})
复制代码
AMD模块定义的方法很是清晰,不会污染全局环境,可以清楚地显示依赖关系。
3.CMD
CMD规范基本语法
定义暴露模块:
//定义没有依赖的模块
define(function(require, exports, module){
exports.xxx = value
module.exports = value
})
复制代码
//定义有依赖的模块
define(function(require, exports, module){
//引入依赖模块(同步)
var module2 = require('./module2')
//引入依赖模块(异步)
require.async('./module3', function (m3) {
})
//暴露模块
exports.xxx = value
})
复制代码
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
复制代码
4.ES6模块化
ES6模块化语法
/** 定义模块 math.js **/
var basicNum = 0;
var add = function (a, b) {
return a + b;
};
export { basicNum, add };
/** 引用模块 **/
import { basicNum, add } from './math';
function test(ele) {
ele.textContent = add(99 + basicNum);
}
复制代码
export default命令,为模块指定默认输出。
// export-default.js
export default function () {
console.log('foo');
}
// import-default.js
import customName from './export-default';
customName(); // 'foo'
复制代码
ES6 模块与 CommonJS 模块的差别
它们有两个重大差别:
① CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
② CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
ES6 在语言标准的层面上,实现了模块功能,并且实现得至关简单,彻底能够取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
虽然依赖了某个模块,但其实只使用其中的某些功能。经过 tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。