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变成什么。都不会影响到模块的暴露内容。其他模块拿到的还是空对象。

完美!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值