JS是脚本语言,脚本语言都需要一个解析器才能运行。对于写在HTML页面里的JS,浏览器充当了解析器的角色。而对于需要独立运行的JS,NodeJS就是一个解析器。每一种解析器都是一个运行环境,其内部提供的方法也不同。
安装使用
官网下载安装node,支持交互式命令模式。在终端通过$ node
即可。常用来测试正则。nodeJs使用CommonJS规范。
模块
使用方式
require
:用于在当前模块中加载和使用别的模块,传入一个模块名,返回一个模块导出对象。
1 | const foo = require('./foo'); //相对引入,后缀js可以省略(绝对引入类似) |
exports
:当前模块的导出对象,用于导出模块公有方法和属性。
1 | exports.hello = function () { |
module
:可以访问到当前模块的一些相关信息,但最多的用途是替换当前模块的导出对象。
1 | module.exports = function () { |
模块解析规则
内置模块
nodeJs内置模块,传递内置模块名称,不做路径解析,例如require('path')
node_modules目录
node_modules
目录用于nodeJs存放模块,例如引入require('foo/bar')
。解析如下:
1 | /home/user/node_modules/foo/bar |
NODE_PATH环境变量
nodeJs允许指定NODE_PATH,环境变量中包含一到多个目录路径,路径之间在Linux下使用:分隔,在Windows下使用;分隔。设置NODE_PATH=/home/user/lib:/home/lib
,解析如下:
1 | /home/user/lib/foo/bar |
npm常用
包管理,nodeJs自带。下载三方包使用:
1 | npm install <packages>; |
文件操作
文件操作示例
node内置模块,详细api见http://nodejs.cn/api/fs.html。
nodeJs只提供基础操作API。实现小文件拷贝如下:
1 | var fs = require('fs'); //内置fs模块 |
上述方法在一次读取过多到内存中时,会出现内存爆满的问题。大文件拷贝如下:
1 | var fs = require('fs'); |
文件操作API
点击标题可跳转node中文网相关API。
Buffer(数据块)
全局构造函数Buffer扩展JS二进制数据类型。Buffer不同于字符串只读,它可以通过[index]
的方式修改。slice
类似与指针,修改会改变原Buffer。交互式命令模式下运行如下:
1 | var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]); //构造Buffer |
Stream(数据流)
NodeJS中通过各种Stream
来提供对数据流的操作。所有的流都是 EventEmitter 的实例。大文件拷贝如下:
1 | //处理数据前暂停数据读取,并在处理数据后继续读取数据 |
File System(文件系统)
NodeJS通过fs内置模块提供对文件的操作。大致分三类:
- 文件属性读写。常用
fs.stat
、fs.chmod
、fs.chown
等等。 - 文件内容读写。常用的有
fs.readFile
、fs.readdir
、fs.writeFile
、fs.mkdir
等等。 - 底层文件操作。常用的有
fs.open
、fs.read
、fs.write
、fs.close
等等。
异步回调,同步API比异步尾部多Sync。
Path(路径)
NodeJS提供了path内置模块来简化路径相关操作,并提升代码可读性。
常用的几个如下:
path.normalize
将传入的路径转换为标准路径。
1 | var cache = {}; |
path.join
将传入的多个路径拼接为标准路径。
1 | path.join('foo/', 'baz/', '../bar'); // => "foo/bar" |
path.extname
根据不同文件扩展名做不同操作时。
1 | path.extname('foo/bar.js'); // => ".js" |
遍历
递归算法
1 | //代码简洁,重复掉用函数自身,消耗性能。 |
遍历算法
深度优先(优先子节点)+先序遍历算法(成功就返回结果,中断循环)。遍历顺序是A > B > D > E > C > F。
1 | A |
同步遍历
1 | function travel(dir, callback) { |
异步遍历
1 | function travel(dir, callback, finish) { |
文本编码
NodeJS编写前端工具时。常用的文本编码有UTF8和GBK两种,但UTF8文件还可能带有BOM。
BOM(Byte Order Marker)用于标记一个文本文件使用Unicode编码,其本身是一个Unicode字符(”\uFEFF”),位于文本文件头部。在不同的Unicode编码下,BOM字符对应的二进制字节如下:
Bytes | Encoding |
---|---|
FE FE | UTF16BE |
FE FE | UTF16LE |
EF BB BF | UTF8 |
Linux系统使用的 UTF32;
UTF16-LE和UTF16-BE,与计算机的CPU构架有关,常用*86系统,通常为UTF16LE(Little Endian);
一个中文字符需要3个字节才能表示。
使用nodeJs读取文件需要去掉BOM,如下:
1 | function readText(pathname) { |
使用iconv-lite
第三方包转换nodeJs不支持的GBK为UTF8,如下:
1 | var iconv = require('iconv-lite'); |
NodeJS中自带了一种binary
编码可以用来实现单字节编码,用来处理未知文本编码的情况
1 | function replace(pathname) { |
网络操作
简单示例
1 | var http = require('http'); |
linux系统下,监听1024以下端口需要root权限
网络操作API
http(HTTP)
http
模块提供两种使用方式:
- 作为服务端使用时,创建一个HTTP服务器,监听HTTP客户端请求并返回响应。
- 作为客户端使用时,发起一个HTTP客户端请求,获取服务端响应。
服务端请求:
1 | //请求内容 |
1 | http.createServer(function (request, response) { |
服务端响应:
1 | //响应内容 |
1 | http.createServer(function (request, response) { |
客户端请求:
1 | var options = { |
1 | http.get('http://www.example.com/', function (response) { |
https(HTTPS)
https和http类似,区别在于https模块需要额外处理SSL证书。
服务端创建服务:
1 | //比http多一个option对象,通过key和cert字段指定了HTTPS服务器使用的私钥和公钥。 |
客户端与http无区别,但如果目标服务器自制SSL,并非颁发机构购买的,默认情况下https模块会拒绝连接,提示说有证书安全问题。可禁用检查,满足开发环境自制SSL证书。
1 | var options = { |
URL(网址)
1 | href |
1 | // url.parse可以将URL字符串解析为URL对象 |
Query String(查询字符串)
querystring模块用于实现URL参数字符串与参数对象的互相转换
1 | querystring.parse('foo=bar&baz=qux&baz=quux&corge'); |
Zlib(压缩)
1 | //判断了客户端是否支持gzip,并在支持的情况下使用zlib模块返回gzip之后的响应体数据 |
1 | var options = { |
Net(网络)
net模块可用于创建Socket服务器或Socket客户端。
进程管理
进程管理示例
通过终端命令简化文件复制功能:
1 | var child_process = require('child_process'); |
进程管理API
Process
在NodeJS中,可以通过process对象感知和控制NodeJS自身进程的方方面面。process是一个全局对象,在任何地方都可以直接使用。
Child Process
使用child_process模块可以创建和控制子进程。该模块提供的API中最核心的是.spawn,其余API都是针对特定使用场景对它的进一步封装,算是一种语法糖。
Cluster
cluster模块是对child_process模块的进一步封装,专用于解决单进程NodeJS Web服务器无法充分利用多核CPU的问题。