模块中exports

在Node.js中,以模块为单位划分所有功能,并且提供了一个完整的模块加载机制,这时的我们可以将应用程序划分为各个不同的部分。狭义的说,每一个JavaScript文件都是一个模块;而多个JavaScript文件之间可以相互require,他们共同实现了一个功能,他们整体对外,又称为一个广义上的模块。

Node.js中,一个JavaScript文件中定义的变量、函数,都只在这个文件内部有效。当需要从此JS文件外部引用这些变量、函数时,必须使用exports对象进行暴露。使用者要用require()命令引用这个JS文件。如下实例:

foo.js文件中的代码:

var msg = "你好";  //msg这个变量,是一个js文件内部才有作用域的变量,如果别人想用这个变量,那么就要用exports进行暴露。
exports.msg=msg;

使用者:

var foo = require("./foo.js"); //使用者用foo来接收exports对象,也就是说,这里的foo变量,就是文件中的exports变量。
console.log(foo.msg);

一个JavaScript文件,可以向外exports无数个变量、函数。但是require的时候,仅仅需要require这个JS文件一次。使用的它的变量、函数的时候,用点语法即可。所以,无形之中,增加了一个顶层命名空间。所有的函数、变量都要从这个顶层变量走:

 如下实例:

var msg = "你好";
var info = "呵呵";

function showInfo(){
    console.log(info);
}

exports.msg = msg;
exports.info = info;
exports.showInfo = showInfo;

在使用者中,只需要require一次。

var foo = require("./foo.js");
console.log(foo.msg);
console.log(foo.info);
foo.showInfo();

exports和module.export的区别

对于module.exports与exorts的区别,了解了下面几点之后应该就完全明白:

模块内部大概是这样:

exports = module.exports = {};  
  • exports是module.exports的一个引用
  • require引用模块后,返回给调用者的是module.exports而不是exports
  • exports.xxx,相当于在导出对象上挂属性,该属性对调用模块直接可见
  • exports =相当于给exports对象重新赋值,调用模块不能访问exports对象及其属性
  • 如果此模块是一个类,就应该直接赋值module.exports,这样调用者就是一个类构造器,可以直接new实例

我们经常看到这样的写法:

exports = module.exports = somethings
上面的代码等价于:
module.exports = somethings
exports = module.exports

即 module.exports 指向新的对象时,exports 断开了与 module.exports 的引用,那么通过 exports = module.exports 让 exports 重新指向 module.exports 即可。

结论:

  • 对于要导出的属性,可以简单直接挂到exports对象上
  • 对于类,为了直接使导出的内容作为类的构造器可以让调用者使用new操作符创建实例对象,应该把构造函数挂到module.exports对象上,不要和导出属性值混在一起

require

  • 在require中,如果没有写./,则该路径不是一个相对路径。那么Node.js将该文件视为node_modules目录下的一个文件
var foo = require("foo.js");   //没有写./, 所以不是一个相对路径。则node将会从node_modules这个文件夹下面去选择foo.js这个文件

node_modules文件夹并不一定在同级目录里面,在任何直接祖先级目录中,都可以。甚至可以放到NODE_PATH环境变量的文件夹中。这样做的好处是,分享项目的时候,不需要带着modules一起给别人。

  • 我们可以使用文件夹来管理模块,如果require中,引入的是一个文件夹,那么Node.js将会去寻找node_modules目录下的该文件夹中的index.js去执行。如下实例
var bar = require("bar"); //node将会去查找node_modules下的bar文件夹中的index.js执行

 关于路径问题

require()中的路径,是从当前这个js文件出发,找到别人。而fs等其他模块是从命令提示符找到别人。

有如下结构的一个实例:

a要引用b:

var b = require(“./test/b.js”);

b要引用c:

var b = require(“./c.js”);

但是,fs等其他的模块用到路径的时候,都是相对于cmd命令光标所在位置。所以,在b.js中想读1.txt文件,如果用相对路径,并且不是在当前文件中,会报一个错,如下:

var c=require("./c.js");
var fs=require("fs")
fs.readFile("./1.txt",function (err,data) {
    if(err) { throw err; }
    console.log(data.toString());
});

运行结果:

 

所以除了require中,nodejs中都建议采用绝对路径,如下:

var c=require("./c.js");
var fs=require("fs")
fs.readFile(__dirname+"/1.txt",function (err,data) {
    if(err) { throw err; }
    console.log(data.toString());
});

 

posted on 2017-11-29 15:36  小之  阅读(164)  评论(0编辑  收藏  举报