javascript模塊化詳解1(基礎和commonjs)

1、模塊化的由來

一、最先咱們這麼寫代碼

所有方法寫在一塊兒,容易命名衝突,而且污染global全局javascript

function foo(){}
function bar(){}

二、簡單封裝(Namespace模式)

減小了全局的變量,可是仍然能夠經過myFunc.foo去操做數據,不安全html

var myFunc = {
    _private:'no safe',
    foo: function(){
        console.log(this._private)
    }
}
myFunc._private = 5;
myFunc.foo();

三、匿名閉包(IIFE模式)

函數時javascript中惟一的localScope, 沒法操做裏面的數據前端

var module = (function(){
    var _private = 'safe now';
    var foo = function(){
        console.log(_private);
    }
    return {
        foo:foo
    }
})();

或者

(function(){
    var _private = 'safe now';
    var foo = function(){
        console.log(_private);
    }
    // 暴露模塊
    window.module = {
        foo:foo
    }
})()

module._private; // undefined 
module.foo();

四、加強,引入依賴

有時候,咱們的功能須要依賴模塊才能完成,此時須要蔣模塊注入進來java

// 這就是模塊模式的基礎
var module = (function($){
    var _private = $('body');
    var foo = function(){
        console.log(_private);
    }
    // 暴露模塊
    return {
        foo:foo
    }
    // 引入模塊
})(JQuery);

或者

(function(global){
    var _private = 'safe';
    var foo = function(){
        console.log(_private);
    }
    // 暴露模塊
    global.module = {
        foo:foo
    }
     // 引入模塊
})(window)

module.foo();

2、模塊化規範

一、commonjs

暴露模塊:默認exports是{}, 第一種至關於把exports覆蓋了,第二種至關於時往exports中添加屬性。node

  • module.exports = value;
  • exports.xxx = value;

引入模塊:web

  • 引入第三方模塊: require(包的名稱)
  • 引入自定義模塊: require(模塊的文件路徑)

實現:npm

  • 服務器端:node環境直接使用
  • 瀏覽器端:使用browserify打包工具 不然瀏覽器不能識別json

    browserify src/app.js -o bundle.js

代碼演示:segmentfault

// module1.js
module.exports = {
    msg: 'module1',
    foo: function () {
        console.log(this.msg);
    }
};
// module2.js
module.exports = function () {
    console.log('module2');
};
// module3.js
exports.foo = function () {
    console.log('foo module3');
};
exports.bar = function () {
    console.log('bar module3');
};
exports.arr = [1, 224, 2, 4, 2, 4784, 3];
// app.js
const uniq =require('uniq')
const module1 = require('./module1');
const module2 = require('./module2');
const module3 = require('./module3');
module1.foo();
module2();
module3.foo();
module3.bar();
console.log(uniq(module3.arr));

3、commonjs詳解

一、模塊載入策略

Node.js的模塊分爲兩類:數組

  • 原生(核心)模塊:原生模塊在Node.js源代碼編譯的時候編譯進了二進制執行文件,加載的速度最快。
  • 文件模塊:文件模塊是動態加載的, 加載速度比原生模塊慢。

Tips:Node.js對原生模塊和文件模塊都進行了緩存,因而在第二次require時,是不會有重複開銷的。其中原生模塊都被定義在lib這個目錄下面,文件模塊則不定性。

二、require文件查找策略

clipboard.png

要點:

  • 優先從文件模塊的緩存中加載
  • 原生模塊的優先級僅次於文件模塊緩存的優先級
  • 原生模塊也有一個緩存區,一樣也是優先從緩存區加載

require方法接受如下幾種參數的傳遞:

  • http、fs、path等,原生模塊。(node自帶的模塊)
  • /mod或../mod,相對路徑的文件模塊。
  • /pathtomodule/mod,絕對路徑的文件模塊。
  • mod, 非原生模塊的文件模塊。(npm包)

module path的生成規則爲

// 從當前文件目錄開始查找node_modules目錄
// 而後依次進入父目錄,查找父目錄下的node_modules目錄
// 依次迭代, 直到根目錄下的node_modules目錄
[
    '/home/jackson/research/node_modules',
    '/home/jackson/node_modules',
    '/home/node_modules',
    '/node_modules'
]
// 除此以外還有一個全局module path,是當前node執行文件的相對目錄 (../../lib/node)。
// 若是在環境變量中設置了HOME目錄和NODE_PATH目錄的話,整個路徑還包含NODE_PATH和HOME目錄下的.node_libraries 與.node_modules
[
    NODE_PATH,
    HOME/.node_modules,
    HOME/.node_libraries,
    execPath/../../lib/node
]

clipboard.png

三、包結構

  • 一個package.json文件應該存在於包頂級目錄下。
  • 二進制文件應該包含在bin目錄下。
  • JavaScript代碼應該包含在lib目錄下。
  • 文檔應該在doc目錄下。
  • 單元測試應該在test目錄下。

Node.js在沒有找到目標文件時,會將當前目錄看成一個包來嘗試加載,因此在package.json文件中最重要的一個字段就是main。對於require,只須要main屬性便可。
可是在除此以外包須要接受安裝、卸載、依賴管理,版本管理等流程,因此CommonJS爲package.json文件定義了以下一些必須的字段

  • name : 包名,須要在NPM上是惟一的。不能帶有空格。
  • description : 包簡介。一般會顯示在一些列表中。
  • version : 版本號。一個語義化的版本號(http://semver.org/),一般爲x.y.z。該版本號十分重要,經常用於一些版本控制的場合。
  • keywords : 關鍵字數組。用於NPM中的分類搜索。
  • maintainers : 包維護者的數組。數組元素是一個包含name、email、web三個屬性的JSON對象。
  • contributors : 包貢獻者的數組。第一個就是包的做者本人。在開源社區,若是提交的patch被merge進master分支的話,就應當加上這個貢獻patch的人。格式包含name和email。

    "contributors": [{
             "name": "Jackson Tian", "email": "mail @gmail.com"
         }, {
             "name": "fengmk2", "email": "mail2@gmail.com"
     }],
  • bugs : 一個能夠提交bug的URL地址。能夠是郵件地址 (mailto:mailxx@domain),也能夠是網頁地址(http://url)。%E3%80%82)
  • licenses : 包所使用的許可證。例如:

    "licenses": [{
         "type": "GPLv2",
         "url": "http://www.example.com/licenses/gpl.html",
     }]
  • repositories : 託管源代碼的地址數組。
  • dependencies : 當前包須要的依賴。這個屬性十分重要,NPM會經過這個屬性,幫你自動加載依賴的包。

其它請參考一下連接:
深刻Node.js的模塊機制
詳解JavaScript模塊化開發
前端模塊化詳解(完整版)

相關文章
相關標籤/搜索