node.js module初步理解,exports与module.exports的区别

在开发一个复杂的应用程序的时候,我们需要把各个功能拆分、封装到不同的文件,在需要的时候引用该文件。没人会写一个几万行代码的文件,这样在可读性、复用性和维护性上都很差,几乎所有的编程语言都有自己的模块组织方式,比如Java中的包、C#中的程序集等,node.js使用模块和包来组织,其机制实现参照了CommonJS标准,虽未完全遵守,但差距不大,使用起来非常简单。

在node.js中模块与文件是一一对应的,也就是说一个node.js文件就是一个模块,文件内容可能是我们封装好的一些JavaScript方法、JSON数据、编译过的C/C++拓展等,在关于node.js的误会提到过node.js的架构

其中http、fs、net等都是node.js提供的核心模块,使用C/C++实现,外部用JavaScript封装。

创建、加载模块

在node.js中创建模块非常简单,一个文件就是一个模块,所以我们创建一个calc.js文件就创建了一个模块

var add = function(a,b){

return a+b;

}

var minus = function(a,b){

return a - b;

}

那么我们该如何调用呢? 用require调用。

在test.js中调用:

var calc = require("./calc");

console.log(calc.add(1,2));

可是调用了为什么会报错呢?   因为在calc.js中没有exports。

我们在calc.js中添加

exports.add = add;

exports.minus = minus;

重新运行:node  test.js    结果显示:3    没错了。

可是为什么从网上看到别人用module.exports 呢? 它和exports 有什么区别呢?是不是一样?

其实,Module.exports才是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是Module.exports而不是exports。

所有的exports收集到的属性和方法,都赋值给了Module.exports。当然,这有个前提,就是Module.exports本身不具备任何属性和方法。如果,Module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。

修改calc.js 代码如下:

module.exports =‘ROCK IT!‘;

var add = function(a,b){

return a+b;

}

var minus = function(a,b){

return a - b;

}

exports.add = add;

exports.minus = minus;

再次运行:node  test.js

出现以下错误:

TypeError: Object ROCK IT! has no method ‘add‘

发现报错:对象“ROCK IT!”没有name方法

rocker模块忽略了exports收集的name方法,返回了一个字符串“ROCK IT!”。由此可知,你的模块并不一定非得返回“实例化对象”。你的模块可以是任何合法的javascript对象--boolean, number, date, JSON, string, function, array等等。

你的模块可以是任何你设置给它的东西。如果你没有显式的给Module.exports设置任何属性和方法,那么你的模块就是exports设置给Module.exports的属性。

下面例子中,你的模块是一个类:

代码如下:

module.exports = function(name, age) {

this.name = name;

this.age = age;

this.about = function() {

console.log(this.name +‘ is ‘+ this.age +‘ years old‘);

};

};

可以这样应用它:

代码如下:

var Singer = require(‘./singer.js‘);

var r = new Singer(‘Bao‘, 62);

r.about(); // Bao is 62 years old

下面例子中,你的模块是一个数组:

代码如下:

module.exports = [‘Bao ‘, ‘Liu Dehua‘, ‘Zhou Jielun‘, ‘Lin Junjie‘, ‘Allen Iverson‘];

可以这样应用它:

代码如下:

var rocker = require(‘./singer.js‘);

console.log(‘Singer a great singer: ‘ + rocker[2]); //Singer a greate singer: Zhou Jielun

module.exports与exports

事实的情况是这样的,其实module.exports才是模块公开的接口,每个模块都会自动创建一个module对象,对象有一个modules的属性,初始值是个空对象{},module的公开接口就是这个属性——module.exports。既然如此那和exports对象有什么关系呢?为什么我们也可以通过exports对象来公开接口呢?

为了方便,模块中会有一个exports对象,和module.exports指向同一个变量,所以我们修改exports对象的时候也会修改module.exports对象,这样我们就明白网上盛传的module.exports对象不为空的时候exports对象就自动忽略是怎么回事儿了,因为module.exports通过赋值方式已经和exports对象指向的变量不同了,exports对象怎么改和module.exports对象没关系了。

一次加载

无论调用多少次require,对于同一模块node.js只会加载一次,引用多次获取的仍是相同的实例,看个例子

test.js

var name=‘‘;

function setName(n){
    name=n;
} 

function printName(){
    console.log(name);
}

exports.setName=setName;
exports.printName=printName;

index.js

var test1=require(‘./test‘),
    test2=require(‘./test‘);

test1.setName(‘Bao Zhiqiang‘);
test2.printName();

require搜索module方式

node.js中模块有两种类型:核心模块和文件模块,核心模块直接使用名称获取,比如最长用的http模块

var http=require(‘http‘); 

在上面例子中我们使用了相对路径 ‘./test‘来获取自定义文件模块,那么node.js有几种搜索加载模块方式呢?

  1. 核心模块优先级最高,直接使用名字加载,在有命名冲突的时候首先加载核心模块文件模块只能按照路径加载(可以省略默认的.js拓展名,不是的话需要显示声明书写)

    1. 绝对路径
    2. 相对路径
  2. 查找node_modules目录,我们知道在调用 npm install <name> 命令的时候会在当前目录下创建node_module目录(如果不存在) 安装模块,当 require 遇到一个既不是核心模块,又不是以路径形式表示的模块名称时,会试图
    在当前目录下的 node_modules 目录中来查找是不是有这样一个模块。如果没有找到,则会 在当前目录的上一层中的 node_modules 目录中继续查找,反复执行这一过程,直到遇到根 目录为止。

注:本文章是参考别人的博客,加上自己的理解写的,本人奔着学习的目的写的。如果文中内容有雷同的,请不要介意。本人并没有抄袭的意思,目的是记录传播知识。

参考文献:

1、

node.js module初步理解  http://www.cnblogs.com/dolphinX/p/3485260.html

2、

nodejs中exports与module.exports的区别详细介绍  http://www.2cto.com/kf/201302/191594.html

node.js module初步理解,exports与module.exports的区别

时间: 2024-08-25 12:32:18

node.js module初步理解,exports与module.exports的区别的相关文章

运行node.js报错:Cannot find module &#39;../build/Release/bson&#39;] code: &#39;MODULE_NOT_FOUND&#39; } js-bson

具体报错内容: { [Error: Cannot find module '../build/Release/bson'] code: 'MODULE_NOT_FOUND' } js-bson: Failed to load c++ bson extension, using pure JS version   第一步: 找到 module mongodb ..node_modules\mongodb\node_modules\bson\ext\index.js 并改变bson引用的路径 bso

node.js的初步见解

Node.js 是一个基于 Chrome JavaScript 运?时建立的平台, 用于方便地搭建响应速度快.易于扩展的?络应?.Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和?效,?常适合在分布式设备上运行的数据密集型的实时应用.V8 引擎执行 Javascript 的速度非常快,性能非常好.Node 是一个 Javascript 运行环境(runtime). 实际上它是对 Google V8 引擎进行了封装. Node 对一些特殊用例进行了优化, 提供了替代的 API,使得

详细说明 配置 Sublime Text 开发node.js(windows)包括sub2和sub3的区别

1.先安装Sublime Text  2或者3皆可 2.下载 sublime Text 的nodejs插件 得到那个zip包(后面会介绍用Package Control安装) 3.下载后解压 直接改名为nodejs(一定是这个名字,否则sub2里编辑default文件会报错) 放到 Preferences-->浏览程序包Browse Packages所在的文件夹. 4.打开刚才的nodejs文件夹 找到根目录里面的 Nodejs.sublime-build文件 如下 { "cmd"

Node.js学习之(第二章:exports和module.exports)

前言 Node中,每个模块都有一个exports接口对象,我们需要把公共的方法或者字符串挂载在这个接口对象中,其他的模块才可以使用. Node.js中只有模块作用域,默认两个模块之间的变量,方法互不冲突,互不影响,这样就导致一个问题,我们怎样使用加载进来的模块中的方法呢?这就需要在另外一个模块exports接口对象中挂载模块中公共的方法. exports 我们在a.js中有以下代码: let foo = 'hello' function add (x, y) { return x+y } exp

来源于知乎大神对node.js的形象理解

先复习小学语文课文,华罗庚的<统筹方法>. 比如,想泡壶茶喝.当时的情况是:开水没有:水壶要洗,茶壶茶杯要洗:火生了,茶叶也有了.怎么办? 办法甲:洗好水壶,灌上凉水,放在火上:在等待水开的时间里,洗茶壶.洗茶杯.拿茶叶:等水开了,泡茶喝. 办法乙:先做好一些准备工作,洗水壶,洗茶壶茶杯,拿茶叶:一切就绪,灌水烧水:坐待水开了泡茶喝. 办法丙:洗净水壶,灌上凉水,放在火上,坐待水开:水开了之后,急急忙忙找茶叶,洗茶壶茶杯,泡茶喝. 哪一种办法省时间?我们能一眼看出第一种办法好,后两种办法都窝了

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

原文:http://www.hacksparrow.com/node-js-exports-vs-module-exports.html 你肯定对Node.js模块中用来创建函数的exports对象很熟悉(假设一个名为rocker.js的文件): exports.name = function() { console.log('My name is Lemmy Kilmister'); }; 然后你在另一个文件中调用: var rocker = require('./rocker.js'); r

深入理解Node.js基于事件驱动的回调

回调和异步调用的关系 首先明确一点,回调并非是异步调用,回调是一种解决异步函数执行结果的处理方法.在异步调用,如果我们希望将执行的结果返回并且处理时,可以通过回调的方法解决.为了能够更好的区分回调和异步回调的区别,我们来看一个简单的例子,代码如下: function waitFive(name, function_name){ var pus = 0; var currentDate = new Date(); while(pus < 5000){ var now = new Date(); p

Node.js的require()的工作原理

大多数人都知道Node.js中require()函数做什么的,但是有多少人知道它的工作原理呢?我们每天使用它加载库包和模块,但是它的内部行为原理很神秘. 我们追寻Node模块系统的核心: module.js,这个文件包含一个令人惊讶的神奇功能,它负责加载 编译和缓存每个用过的文件,让我们揭开它的神秘面纱. function Module(id, parent) {  this.id = id;  this.exports = {};  this.parent = parent;  // ...

node.js之看懂package.json依赖库版本控制

金天:学习一个新东西,就要持有拥抱的心态,如果固守在自己先前的概念体系,就会有举步维艰的感觉.node.js依赖库的版本控制金天微信:15998603918 欢迎找我聊聊天. 一般node.js项目会依赖大量第三方module, 那么如何控制module的版本呢? 答案通过package.json. "dependencies": { //精确匹配 "async": "1.2.1", //近似 相当于0.7.* "pdfkit"