您的位置:首页 > Web前端 > Node.js

Node中的包和模块

2016-05-07 19:15 645 查看

一、模块和包

概念:模块(Module)和包(Package)是Node.js最重要的支柱。开发一个具有一定规模的程序不可能只用一个文件,通常需要把各个功能拆分、分装、然后组合起来。模块正式为了实现这种方式而诞生,在浏览器JavaScript中,脚本模块的拆分和组合通常使用HTML的script标签来实现,Node.js提供了require函数来调用其他模块,而且模块都是基于文件,机制非常简单,模块和包的区别是透明的,因此经常不作区分。

模块

1.什么是模块

模块和文件是一一对应的。一个Node.js文件就是一个模块,这个文件可能是JavaScript代码、JSON或者编译过的C/C++扩展。

var http=require(‘http’),其中http是Node.js的一个核心模块,通过require函数获取这个模块,然后使用其中的对象.

2.创建和加载模块

(1)创建模块

Node.js提供了exports和require两个对象,其中exports是模块的公开接口,require()是从外部获取一个模块的接口,下面提供了一个例子:

下面是module.js代码:

var name;
exports.setName=function(getName){
name = getName;
}
exports.setHello=function(){
console.log('hello'+name);
}


下面的是getModule.js代码:

var myModule = require('./module');
myModule.setName('helios');
myModule.setHello();


输出是
hellohelios


(2)单次加载

通过require函数得到的这个文件里面有暴露属性的对象(exports),因为require
不会重复加载模块
无论重复加载多少次,获取的模块都是第一个require的,看下面改动后的getModule.js代码

var myModule1 = require('./module');
// 设置myModule1对象的name
myModule1.setName('helios');
var myModule2 = require('./module');
// 设置myModule2对象的name
myModule2.setName('newName');
//调用myModule1的方法setHello
myModule1.setHello();   //输出的是hellonewName
//这就说明了无论怎么改动都是改动了第一次引用的require


(3)覆盖exports

要理解这个问题就先要理解
exports
module.exports
分别是什么意思;

其实在一开始的时候
exports
module.exports
就是一个东西,这里说他们是一个东西其实并不确切,更应该说
exports
module.exports
指向的是同一块内存,为什么这么说呢请看下面这个例子:

console.log(exports  === module.exports);//true
console.log(exports);//{}
console.log(exports == {});//false
console.log(module.exports);//{}
console.log(module.exports  ==  {});//false


exports
赋值就相当于给
module.exports
添加属性,如下面代码:

var name = 'helios';
exports  = name;
exports.setName = function(){}


上面的代码就相当于下面的代码:

var name = 'helios';
module.exports  = name;
module.exports.setName = function(){}


我们通过require的到的其实是一个
module.exports
方法,为什么这么说呢!请看下面的这几个例子:

1.下面是
modul.js


exports.name=function(){
console.log("this is name method");
}


下面这个是
getModule.js


var myModule1 = require('./module');
myModule1.name();


2.下面对
module
这个文件改动了一下:

module.exports=function(){
console.log("this is name method");
}


下面是对
getModule.js
的稍稍改动

var myModule1 = require('./module');
myModule1();


2.
exports
module.exports
指向的是同一块内存那么为什么不用下面这样方法写呢?

下面是对
module.js
的改动

exports=function(){
console.log("this is name method");
}


如果写成了这样不论
geyModule.js
写为什么样子都会报错,这就引出了下面的结论:require返回的其实是
module.exports
这个方法,
exports
其实是指向
module.exports
的一个引用


换一种说法就是这样写法是对
exports
进行了覆盖,也就是说
exports
指向了一块新的内存(因为对他重新赋值了),也就是说无论
exports
怎么变化
module.exports
内存都是没有的不会变化,我们在
getModule.js
引入了一个空对象肯定会报
myModule1 is not a function
这样的错误。

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

exports = module.exports = somethings


上面的代码就等价于:

module.exports = somethings//对module.exports进行覆盖
exports = module.exports  //对exports进行覆盖


这就是为了保证
exports
module.exports
还是指向的是同一块内存;

有的时候为了方便我们会把所有的方法或者属性都放在构造函数里面,然后在对方暴露这个构造函数:

下面是
module.js


function hello(){
var name;
this.setName=function(thyName){
name=thyName;
}
this.sayHello=function(){
console.log('hello '+name);
}
}
//exports.hello=hello;
module.exports=hello;


下面是
getModule.js


var hello=require('./module');
var he=new hello();//helloundefined
he.setName('shangyilong');
he.sayHello();//helloshangyilong
var he2=new hello();
he2.setName('helios');
he2.sayHello();//hellohelios


这样就能克服require单次加载的弊端了。

1.包的概念

包是在模块基础上更深一步的抽象,Node.js的包类似于C/C++的函数库或者java的类库,它讲某个独立的功能封装起来,用于发布、更新、依赖管理的版本控制。开发了npm来解决包的发布和获取需求。

包是由
package.json
定义的文件或目录

我们通过npm install XX 后面的XX就是包

我们可以通过
npn init
初始化一个包。我们可以把这个包做大然后上传到nodejs给别人使用

这是Node的一个系列,可以在本栏目下看其他关于Node文章,会 一直更新,有问题请在下方留言
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: