一起读nodejs(三)----模块(Modules)
模块(Modules)
stability:5 -locked
node有一个简单的模块加载机制.在node里面文件和模块是 一对一 对应的.例如,foo.js加载在同一文件夹下的circle.js模块.
foo.js的内容:
[javascript]
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
+ circle.area(4));</SPAN>
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
+ circle.area(4)); circle.js的内容:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};</SPAN>
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
}; circle.js模块以导出了area()方法和circumference()方法.为了导出一个对象,需要加上指定的exports对象.
属于模块的变量是私有的.在这个例子中变量PI就是私有于circle.js.
模块机制是在require('module')模块中实现的.
环形加载(Cycles)
当存在环形的require()调用时,当一个模块被返回被执行的时候,可能还没有加载完成,考虑下面这种情景:
a.js:
[javascript]
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">console.log('a starting');
exports.done = false;
var b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');</SPAN>
console.log('a starting');
exports.done = false;
var b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done'); b.js:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">console.log('b starting');
exports.done = false;
var a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');</SPAN>
console.log('b starting');
exports.done = false;
var a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done'); main.js:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">console.log('main starting');
var a = require('./a.js');
var b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);</SPAN>
console.log('main starting');
var a = require('./a.js');
var b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done); 当main.js加载a.js的时候,a.js依次需要加载b.js.在这时,b.js试着去加载a.js.为了防止一个无穷的循环(loop),一个未完成的a.js的副本的exports导出对象被返回到b.js模块.然后b.js完成加载,然后他的exports导出对象被提供给a.js模块.
当main.js加载完这两个模块的时候,他们都已经加载完.这个程序的输出应该这样子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done=true, b.done=true</SPAN>
$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done=true, b.done=true 如果你的程序里面有环形的模块依赖,确保制定相应的计划(意思是,确保在所有依赖的模块都加载完时在调用,避免在模块未加载完时,调用导致程序不可预期的结果).
(循环加载,require()方法有对应的机制,上面例子中b.js返回时,b.js加载的a.js没有加载完,但是当b.js加载完时,a.js就加载完了,这时候b.js里面保存的a.js也会被更新成完成的对象,其实我觉得保存的可能就是类似于a.js的引用.)
核心模块(Core modules)
node中有一些模块被编译成二进制. 这些模块在文档的其他地方有更详细的描述.
核心模块被定义在node的源码中的lib文件夹下.
如果核心模块的标识符被传入require()方法时,总是被优先加载.例如,require('http')将总是返回内置的http模块,即使当前有一个同名的模块文件夹.
文件模块加载机制(File modules)
如果准确的文件名字没有找到,node将会试图依次加载添加了.js,.json,.node等后缀名的文件.
.js文件被当作javascript文本文件解读,.json文件被转换成json文本文件. .node文件被当做已经编译好的插件模块,使用dloopen加载.(在dlopen()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。)
当一个模块的前缀是"/"时,表示一个模块文件的绝对路径.例如:require('/home/marco/foo.js')将会使用'/home/marco/foo.js'作为路径加载.
当一个模块的前缀是"./"时,表示一个模块文件的相对路径调用require().例如:为了让foo.js中的require('./circle.js')能被找到,circle.js必须和foo.js在同一目录下.
如果没有"./"或者"/"当文件前缀,这个模块不是一个核心模块,就是一个需要从node_modules文件夹中加载的模块.
如果给定的加载路径不存在,requier()方法将会抛出一个Error错误对象,并且Error的code属性被设置成:'MODULE_NOT_FOUND'.
从node_modules文件夹加载模块(loading from node_mudoles folders)
如果传入到require()方法中的模块标识符不是本地模块,并且也不是"/","../",或者"./"开头,node则会在当前模块的父目录路径上追加/node_modules,以这个路径试图加载模块.
如果这里也没有找到,node会继续移动到更上一层的父目录,等等...直到到达根目录.
例如,文件'/home/ry/project/foo.js'中调用require('bar.js'),node会查找以下列出的路径,依次是:
/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
这将允许程序本地化他们的依赖,以便不产生冲突.
文件夹就是模块(Floder as modules)
组织程序和类库放进自己包含的目录下是很方便的,然后提供一个单独的入口指定这个类库,有三种方法把一个文件夹作为一个参数传进require()方法.
第一种方法是在根目录创建一个package.json文件,指定一个主模块.一个paceage.json的例子看起来像这样子:
[javascript]
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">{ "name" : "some-library",
"main" : "./l
补充:web前端 , JavaScript ,