本文转自Node.js module.exports与exports
做者: chemdemojavascript
折腾Node.js有些日子了,下面将陆陆续续记录下使用Node.js的一些细节。java
熟悉Node.js的童鞋都知道,Node.js做为服务器端的javascript运行环境,它使用npm做为通用的包管理工具,npm遵循CommonJS规范定义了一套用于Node.js模块的约定,关于npm实现Node.js模块的更多细节请细读深刻Node.js的模块机制,这里简单讲下书写Node.js代码时module.exports与exorts的区别。git
在浏览器端js里面,为了解决各模块变量冲突等问题,每每借助于js的闭包把全部模块相关的代码都包装在一个匿名函数里。而Node.js编写模块至关的自由,开发者只须要关注require,exports,module等几个变量就足够,而为了保持模块的可读性,很推荐把不一样功能的代码块都写成独立模块,减小各模块耦合。开发者能够在“全局”环境下任意使用var申明变量(不用写到闭包里了),经过exports暴露接口给调用者。github
咱们常常看到相似export.xxx = yyy
或者module.exports = xx
这样的代码,可实际在经过require
函数引入模块时会出现报错的状况,这是什么缘由致使的呢?npm
Node.js在模块编译的过程当中会对模块进行包装,最终会返回相似下面的代码:浏览器
(function (exports, require, module, __filename, __dirname) { // module code... });
其中,module就是这个模块自己,require是对Node.js实现查找模块的模块Module._load实例的引用,__filename和__dirname是Node.js在查找该模块后找到的模块名称和模块绝对路径,这就是官方API里头这两个全局变量的来历。服务器
关于module.exports与exorts的区别,了解了下面几点以后应该就彻底明白:闭包
模块内部大概是这样:函数
exports = module.exports = {};
假若有模块a.js代码以下:工具
exports.str = 'a'; exports.fn = function() {};
对a模块的调用:
var a = require('./a'); console.log(a.str); console.log(a.fn());
这样用是对的,若是改造a以下:
exports.str = 'a'; exports = function fn() {};
在调用a模块时天然没用fn属性了。
再改造下a模块:
exports.str = 'a'; module.exports = function fn() {};
这时a模块其实就是fn函数的引用,也就是说能够require('./a')()这样使用,而同时再也不有str属性了。
下面直接导出一个类:
module.exports = function A() {};
调用:
var A = require('./a'); var a = new A();
总结下,有两点: