了解Node.js的模块、包、包管理器

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

一、模块

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

2.Node.js提供了exports和require两个对象,其中exports是模块公开的接口,require用于从外部获取一个模块的接口,即所获取模块的exports对象。

3.一个文件就是一个模块。

第一个例子,如何创建一个模块,先创建一个module.js文件:

var name;
exports.setName = function(thyName){
	name = thyName;
};
exports.sayHello = function(){
	console.log('Hello' + name);
};
再在同一个目录创建getmodule.js

var myModule = require('./module');
myModule.setName('BYVoid');
myModule.sayHello();
最后cmd进入该目录运行node getmodule.js即可


原理:module.js通过exports对象把setName和sayHello作为模块的访问接口,在getmodule.js中通过require('./module')加载这个模块,然后就直接访问module.js中的exports对象的成员函数了。

延伸:因为require不会重复加载模块,也就是所无论调用多少次require获得的模块都是同一个。例如修改getmodule.js看效果:

var myModule1 = require('./module');
myModule1.setName('BYVoid');
var myModule2 = require('./module');
myModule2.setName('BYVoid2');
myModule1.sayHello();
运行结果为:


原理:因为变量myModule1和myModule2都是指向同一个实例,因此myModule1.setName的结果被myModule2.setName覆盖了。

第二个例子,覆盖exports,把一个对象封装到模块中:

新建一个singleobject.js

function Hello(){
	var name;
	this.setName = function(thyName){
		name = thyName;
	};
	this.sayHello = function(){
		console.log('HelloSingle' + name);	
	};
};
exports.Hello = Hello;

新建一个hello.js

function Hello(){
	var name;
	this.setName = function(thyName){
		name = thyName;	
	};
	this.sayHello = function(){
		console.log('HelloHello' + name);
	};
};
module.exports = Hello;
再新建一个gethello.js

var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();
运行结果是:


模块接口唯一变化是使用module.exports=Hello代替了exports.Hello=Hello。

exports本身仅仅是一个普通的空对象,即{},它专门用来声明接口,本质上是通过它为模块闭包的内部建立了一个有限的访问接口。因为它没有任何特殊的地方,所以可以用其他东西来替代,譬如上面例子中的Hello对象。

二、包

包:将某个独立的功能封装起来,用于发布、更新、依赖管理和版本控制。

Node.js对包只要顶层目录下有package.json,并符合一些规范即可。

模块与文件是一一对应的,最简单的包就是一个作为文件夹的模块。

建立一个例子说明作为文件夹的模块:
新建一个文件夹somepackage在其中创建index.js

exports.hello = function(){
	console.log('Hello.');
};
然后在somepackage文件夹之外建立getpackage.js

var somePackage = require('./somepackage');
somePackage.hello();
cmd进入存放getpackage.js地址,node getpackage.js


原理:这种方法可以把文件夹封装为一个模块,即所谓的包。包通常是一些模块的集合,在模块的基础上提供了更高层的抽象,相当于提供一些固定接口的函数库。

通过定制package.json,可以创建更复杂、更完善、更符合规范的包用于发布,建立一个例子说明如下:
在somepackage文件夹下面,新创建一个叫做package.json的文件

{
	"main" : "./lib/interface.js"
}

再在这个文件夹目录下面新建一个lib文件夹和在下面新建一个interface.js

exports.hello = function(){
	console.log('HelloLib');
};
cmd进入存放getpackage.js地址,node getpackage.js

Node.js在调用某个包时,会首先检查包中package.json文件的main字段,将其作为包的接口模块,如果package.json或main字段不存在,会尝试寻找index.js或index.node作为包的接口。【如果既没有在package.json里面说明又没有在index.js或index.node中,就会报找不到此文件的错误哦】

三、包管理器npm

1.获取一个包:npm install/i package_name比如:npm install express或 npm i express。npm默认情况会从http://npmjs.org搜索下载包,将包安装到当前目录的node_modules子目录下面

2.本地模式和全局模式

(1)如果把包安装到全局,可以提高程序的重复利用程度,避免同样的内容多份副本,但坏处是难以处理不同版本依赖

  如果把包安装到当前目录,或者说本地,则不会有不同程序依赖不同版本的包的冲突问题,同时减轻了包作者API兼容性压力,但缺陷是同一个包可能会被安装很多次。

(2)全局模式获取一个包:npm install/i -g package_name

多数情况下并不是因为许多程序都可能用到它,为了减少多重副本而使用全局模式,而是因为本地模式不会注册PATH环境变量。npm本地模式仅仅是把包安装到node_modules子目录下,其中的bin目录没有包含到PATH环境变量中,不能直接在命令行中调用。而全局模式下的supervisor.js就可以直接在命令行中运行supervisor XXX.js即可监控代码改动了。








猜你喜欢

转载自blog.csdn.net/Miss_LL/article/details/53502729