Node.js中的module.exports和exports的区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Picking_up_stones/article/details/75736527

之前有了解Node.js的相关内容,也有用node.js和express框架写过一个个人博客,然而对于一些原理性的知识还是知之甚少,今天看到自己写的博客项目上面有用到exports和module.exports两种方法来导出一些模块,方便之后的模块去引用,就看了下两者的区别。下面是我的总结:


一. 两者的常见用法:

1 . exports的常见用法:

exports.name = 'XXX';
exports.something = function (){
    //...
};

2 . module.exports的常见用法:

function Func(x, y){
    this.x = x;
    this.y = y;
}

Func.prototype.something = function (){
    //...
}

module.exports = Func;

我们可以看出,一般一个js文件中会出现不止一个exports,而且是以添加属性的形式赋值;然而module.exports在一个文件中只出现一次,为什么会有这样的用法呢?我们继续往下看就会真相大白了!

二. module.exports和exports的原理

exports和module都是系统创建的两个对象,在module.exports中的exports只是module的一个属性,在初始化时:exports = module.exports = {};可以看出exports只是module.exports的一个引用。下面来看个js的小例子,就会明白两者的区别了。

var module = {};
module.exports = {};
var exports = module.exports; //exportsmodule.exports指向同一块内存
exports.name = 'luwenjing';
console.log(module.exports.name);  //luwenjing

从上面的例子可以看出,如果给exports添加一个属性,就相当于给module.exports添加了一个属性。那如果改一下module.exports的内存指向呢?

var module = {};
module.exports = {};
var exports = module.exports;
exports.name = 'luwenjing';
module.exports = {};
console.log(module.exports.name);  //undefined

可以看到,如果改了内存指向,module.exports就会指向新的内存,name属性就自然不存在了。
看到这里应该有人会说,这不就是引用类型本身的特性吗,用得着你在这再重复一遍。不急,不急,如果你看到这里已经知道exports和module.exports在用法上的区别的原理时,那你就不用再往下看了,潇洒的离开便好,如果你还有疑问就继续吧!

三. 加深理解

1 . 实际我们在使用require导入模块时,导入的是module.exports的值:

exports.name = 'XXX';
exports.something = function (){
    //...
};

如上面的代码块,以为exports和module.exports指向同一块内存,所以此时的

exports = module.exports = {
    name: 'XXX',
    something: function (){
        //...
    }
}

所以require时也就自然得到了name和something的值。

2 . 那如果在一个js文件中同时存在exports和module.exports会怎样呢?

exports.name = 'XXX';
exports.something = function (){
    //...
};
module.exports = {};

还记得上面的代码的同学就会知道,此时module.exports指向了新的内存,如果我们再用require导入后获得name属性就会输出undefined。


总结:exports是module.exports的引用,所以在使用exports导出时,相当于全部赋给了module.exports,前提是module.exports不具有任何属性和方法,如果module.export已经具备一些属性和方法,那么exports添加的信息将被忽略。因为require始终引入的都是module.exports的值。

所以如果要导出的是一个个单独的属性或方法时用exports;

如果要导出的是一个构造函数或一个对象,其中的属性和方法相互关联就使用module.exports。

猜你喜欢

转载自blog.csdn.net/Picking_up_stones/article/details/75736527