模块
一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。
创建模块
1、创建hello.js
exports.world = function() {
console.log('Hello World');
}
exports 是模块公开的接口,在此例中,world是对外看到的方法名,也就是接口。
2、引入模块
var hello = require('./hello');
hello.world();
在之前的笔记中提到过,和引入node.js本身的模块不同,引入自己书写的模块时,不能只写文件名称,需表明路径,此例表示引入当前目录下的hello.js文件。默认后缀为js,所以文件名中可以省略。
如果想把一个对象封装到模块中:
function Hello() {
var name;
this.setName = function(thyName) {
name = thyName;
};
this.sayHello = function() {
console.log('Hello ' + name);
};
};
module.exports = Hello;
再另一个文件中,直接获取对象:
var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();
模块接口从exports.world = function(){} 变成了 module.exports = Hello
在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的 exports。
服务端的模块放在哪里
require方法接受以下几种参数的传递:
- http、fs、path等,原生模块。
- ./mod或../mod,相对路径的文件模块。
- /pathtomodule/mod,绝对路径的文件模块。
- mod,非原生模块的文件模块。
优先级关系:
- 文件模块的缓存
- 原生模块的缓存区
- 原生模块
- 以http模块为例,尽管在目录下存在一个http/http.js/http.node/http.json文件,require(“http”)都不会从这些文件中加载,而是从原生模块中加载。
- 文件模块
函数
在JavaScript中,一个函数可以作为另一个函数接收一个参数。我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。Node.js中函数的使用与Javascript类似。
- 以HTTP服务器为例
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
var http = require("http");
function onRequest(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
第一段代码向 createServer 函数传递了一个匿名函数。第二段代码则是先定义一个函数,然后传递。
路由
提供请求的URL和其他需要的GET及POST参数,随后路由需要根据这些数据来执行相应的代码。
需要的所有数据都会包含在request对象中,该对象作为onRequest()回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的Node.JS模块,分别是url和querystring模块。
url.parse(string).query
|
url.parse(string).pathname |
| |
| |
------ -------------------
http://localhost:8888/start?foo=bar&hello=world
--- -----
| |
| |
querystring(string)["foo"] |
|
querystring(string)["hello"]
把路由和服务器整合起来
- router.js
function route(pathname) {
console.log("About to route a request for " + pathname);
}
exports.route = route;
输出route作为接口。
- server.js
var http = require("http");
var url = require("url");
function start(route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(pathname);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
输出start作为接口。上段代码中的route方法作为start方法的参数,并在其中调用。url.parse(request.url).pathname用来获取路径名称。
- index.js
var server = require("./server");
var router = require("./router");
server.start(router.route);
引入自己编写的server和router模块。调用start方法,并将route方法作为参数传递。
在命令行输入 node index.js 启动应用。随后请求一个URL,浏览器访问http://localhost(或127.0.0.1):8888(你监听的端口号)/(任意路径名)
全局对象
Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。
当你定义一个全局变量时,这个变量同时也会成为全局对象的属性。
注意: 永远使用var定义变量以免引入全局变量,因为全局变量会污染命名空间,提高代码的耦合风险。
全局对象举例
- __filename
- 当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径。
- __dirname
- 当前执行脚本所在的目录。
- console
- 提供控制台标准输出
- console.log() 接受若干 个参数,如果只有一个参数,则输出这个参数的字符串形式。如果有多个参数,则 以类似于C 语言 printf() 命令的格式输出。
- console.time(label) 表示计时开始,console.timeEnd(label) 表示计时结束。
- console.trace() 向标准错误流输出当前的调用栈。
- process
- 是一个全局变量,即 global 对象的属性。
- 描述当前Node.js 进程状态的对象,提供了一个与操作系统的简单接口。
// 输出到终端
process.stdout.write("Hello World!" + "\n");
// 通过参数读取
process.argv.forEach(function(val, index, array) {
console.log(index + ': ' + val);
});
// 获取执行路局
console.log(process.execPath);
// 平台信息
console.log(process.platform);
首先通过标准输出流进行了打印。argv 属性返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是node,第二个成员是脚本文件名,其余成员是脚本文件的参数。后面两个参数则是Node的路径和平台系统。
process还有很多有用的方法和属性。
// 输出当前目录
console.log('当前目录: ' + process.cwd());
// 输出当前版本
console.log('当前版本: ' + process.version);
// 输出内存使用情况
console.log(process.memoryUsage());
常用工具
- util.inherits
util.inherits(constructor, superConstructor)是一个实现对象间原型继承的函数。
var util = require('util');
function Base() {
this.name = 'base';
this.base = 1991;
this.sayHello = function() {
console.log('Hello ' + this.name);
};
}
Base.prototype.showName = function() {
console.log(this.name);
};
function Sub() {
this.name = 'sub';
}
util.inherits(Sub, Base);
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
//objSub.sayHello();
console.log(objSub);
Sub继承Base,Base有三个在构造函数内定义的属性和一个原型中定义的函数。Sub 仅仅继承了Base 在原型中定义的函数。
输出为:
base
Hello base
{ name: 'base', base: 1991, sayHello: [Function] }
sub
{ name: 'sub' }
- util.inspect
util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换为字符串的方法,通常用于调试和错误输出。
自己加油加油 笨鸟后飞也要飞呀飞