明白 JS 模塊化

模塊化是什麼,有什麼用?

模塊化就是將一個大的功能拆分爲多個塊,每個塊都是獨立的,你不須要去擔憂污染全局變量,命名衝突什麼的。前端

那麼模塊化的好處也就顯然易見了瀏覽器

  • 解決命名衝突
  • 依賴管理
  • 代碼更加可讀
  • 提升複用性

早期苦逼的前端er

可是,JS 這門語言在最初是沒有這個設計的。因此也就苦了早期的前端開發者。下面介紹下最開始的寫法。模塊化

函數封裝

這個嘛,誰都會,最大的缺點就是污染全局做用域了函數

function fn1() {
    // balabalabala
}
function fn2() {
    // balabalabala
}複製代碼

對象

這個嘛,也是誰都會的,最大的缺點就是沒有私有變量,外部能改ui

var myModule = {
    var1: 1,
    fn1: function() {}
}複製代碼

當即執行函數

這個嘛,高級了點,而且也有了模塊化的意思,這種寫法在老項目中很常見,一個 JS 文件中就是一個當即執行函數spa

(function(){
   // ....
})()複製代碼

CommonJS

瀏覽器這邊表示沒有模塊化還行,就是寫邏輯麻煩了點。可是搞服務端的必須得有這玩意啊,因此 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.exportsexports 是咋回事?爲啥這幾句代碼就實現模塊化了,讓咱們來看一下基礎的實現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.exportsexports,用法其實基本是類似的,可是不能對 exports直接賦值,不會有任何效果,看了上面代碼的同窗確定明白爲何了。作用域

CommonJS規範是 Node 獨有的,瀏覽器中使用就須要用到 Browserify 解析了,因此後面又蹦出了兩個規範。

AMD && CMD

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複製代碼
相關文章
相關標籤/搜索