模塊化就是將一個大的功能拆分爲多個塊,每個塊都是獨立的,你不須要去擔憂污染全局變量,命名衝突什麼的。前端
那麼模塊化的好處也就顯然易見了瀏覽器
可是,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複製代碼