Node.js模塊化開發 export和module.export的區別

Node的初學者(包括我自己)都很疑惑,爲什麼有了exports還要module.exports?兩者都有什麼區別?

弄清楚上面兩個問題之前先思考一個問題。來看一個栗子。

let a = 1
let fibonaci = function(n,first=1,sum=1){
    if (n==1||n==2)
        return sum
    else{
        let t = sum;
        sum = first+sum
        first = t
        return fibonaci(n-1,first,sum)
    }
}
exports.fibonaci = fibonaci
let fn = require('./module_1')
console.log(fn.fibonaci(5))

很簡單的一個模塊暴露變量,一個引用。node中使用的語言也是js,我們知道只有對象才能設置屬性。那麼export沒有聲明,它爲什麼可以設置屬性呢?

《深入淺出node.js》中寫到,每一個文件模塊都是一個對象。它的定義如下。


function Module(id, parent) {
    this.id=id
    this.exports = {}
    this.parent = parent;
    if (parent&&parent.children){
        parent.children.push(this)
    }
    this.filename = null
    this.loaded = false 
    this.children = []
}

不用去看id巴拉巴拉parent什麼的。看到this.exports={}。所以說,所有文件模塊都是這個Module的實例對象。自然也就會有exports屬性。

而書中也寫到。node會對獲取到的JavaScript內容進行首尾包裝。

所以一個上文提到的的模塊會被包裝成下面這樣

(function (exports,require,module,_filename,_dirname) {
    let fibonaci = function(n,first=1,sum=1){
        if (n==1||n==2)
            return sum
        else{
            let t = sum;
            sum = first+sum
            first = t
            return fibonaci(n-1,first,sum)
        }
    }
    exports.fibonaci = fibonaci
})

這樣就可以解釋了爲什麼js中沒有定義require和exports卻可以使用,也很好的解釋了引入的變量名不衝突的問題(因爲實際上引入的變量被封裝在一個函數中,可以看成是一個局部變量。局部變量自然不會覆蓋掉全局變量)

言歸正傳。exports和module,exports的區別。

在node中,模塊可以把想暴露出去的變量放在module.exports中,這樣就可以被其他模塊所引用到。而exports只是一個指針。指向module.exports這個對象。

所以說,一開始所有模塊暴露都是module.exports,它是一個空對象。

let fibonaci = function(n,first=1,sum=1){
    if (n==1||n==2)
        return sum
    else{
        let t = sum;
        sum = first+sum
        first = t
        return fibonaci(n-1,first,sum)
    }
}

注意此處,我定義了一個函數,但是沒有exports,也就是說沒有暴露出去,我們來看看其他模塊引用這個模塊時的輸出。

let fn = require('./module_1')
console.log(fn)

不出所料。上面已經說過,exports是指向的module.export的引用,所以說以下這兩種寫法得到的結果會完全一樣。

module.exports.fibonaci = fibonaci
exports.fibonaci = fibonaci

那他們的差別是什麼呢?仔細的分析expors和module.exports的定義。exports是一個指針,指向module.exports,而只有在module.exports中的內容纔會暴露給其他模塊。所以說以下會得到不一樣的結果

首先是module.exports

module.exports='123'

此模塊暴露了123,所以其他模塊引用這個模塊只能拿到123

沒有問題。再來看看exports

exports=123

原來的exports是指向module.exports,現在exports變成了123,不指向module.exports了。但是重點是隻有module.exports中的內容纔會被暴露。所以不管exports變成什麼。都不會影響到模塊的暴露內容。其他模塊拿到的還是空對象。

完美!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章