模块化就是将一个大的功能拆分为多个块,每个块都是独立的,你不须要去担忧污染全局变量,命名冲突什么的。前端
那么模块化的好处也就显然易见了浏览器
可是,JS 这门语言在最初是没有这个设计的。因此也就苦了早期的前端开发者。下面介绍下最开始的写法。模块化
这个嘛,谁都会,最大的缺点就是污染全局做用域了函数
function fn1() {
// balabalabala
}
function fn2() {
// balabalabala
}复制代码
这个嘛,也是谁都会的,最大的缺点就是没有私有变量,外部能改ui
var myModule = {
var1: 1,
fn1: function() {}
}复制代码
这个嘛,高级了点,而且也有了模块化的意思,这种写法在老项目中很常见,一个 JS 文件中就是一个当即执行函数spa
(function(){
// ....
})()复制代码
浏览器这边表示没有模块化还行,就是写逻辑麻烦了点。可是搞服务端的必须得有这玩意啊,因此 Node.js 第一个搞出了 CommonJS规范
。设计
// a.js
module.exports = {
a: 1
}
// or
exports.a = 1
// b.js
var module = require('./a.js')
module.a // -> log 1复制代码
上面的写法很好用,可是 module.exports
和 exports
是咋回事?为啥这几句代码就实现模块化了,让咱们来看一下基础的实现code
先说 require
吧对象
var module = require('./a.js')
module.a
// 这里其实就是包装了一层当即执行函数,这样就不会污染全局变量了,
// 重要的是 module 这里,module 是 Node 独有的一个变量
module.exports = {
a: 1
}
// 基本实现
var module = {
id: 'xxxx', // 我总得知道怎么去找到他吧
exports: {} // exports 就是个空对象
}
// 这个是为何 exports 和 module.exports 用法类似的缘由
var exports = module.exports
var load = function (module) {
// 导出的东西
var a = 1
module.exports = a
return module.exports
};
// 而后当我 require 的时候去找到独特的
// id,而后将要使用的东西用当即执行函数包装下,over复制代码
再来讲说 module.exports
和 exports
,用法其实基本是类似的,可是不能对 exports
直接赋值,不会有任何效果,看了上面代码的同窗确定明白为何了。作用域
CommonJS规范
是 Node 独有的,浏览器中使用就须要用到 Browserify
解析了,因此后面又蹦出了两个规范。
AMD 是由 RequireJS
提出的,CMD 由 SeaJS
提出。二者用法基本类似,固然如今用的人应该也很少了,了解下语法,看项目的时候不至于懵逼就行
// AMD
define(['./a', './b'], function(a, b) {
a.do()
b.do()
})
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
var b = require('./b')
b.doSomething()
})复制代码
ES6总算原生支持模块化了,毁誉参半吧。固然这个语法仍是早支持早好。
// 引入的语法就这样 import,XXX 这里有不少语法变化
import XXX from './a.js'
// 导出也有不少语法变化的写法,基本的就这两个,反正语法没什么可贵
export function a() {}
export default function() {}复制代码
这里基本的介绍了下模块的几种写法,若有错误,请提出,谢谢!
评论里有问到为何直接对 exports
赋值无效。首先 require
出来的是 module.exports
对象,而后看下面的代码
var a = {}
a.exports = {}
// 把 e 当作 exports,如今 e === a.exports
var e = a.exports
// 引用的关系,同时也修改了 a.exports
e.c = 1
console.log(a.exports.c) // -> 1
// 可是当给 e 赋值的话就等于修改了引用了, 因此并无修改 a.exports
e = xxxx复制代码