简介
Node.js是一个服务端JS运行环境
单线程
CommonJS
缺陷:
没有模块化
标准库较少
没有借口标准
缺乏管理系统
NodeJS中, 一个js文件就是一个模块
引入别的模块
通过require()引入模块
如果是相对路径, 一点得以.或者..开头
1  | require("./02.module.js");  | 
使用require()引入模块后, 该函数返回一个模块, 这个对象代表的事引入的模块
1  | var md = require("./02.module.js");  | 
在node中, 每个js文件中的代码, 都是独立运行在一个函数中
不是全局作用域, 所以一个模块的变量和函数在其他模块无法访问
exports
可以通过exports 来向外部暴露变量和方法
1  | exports.x = "我是exports x";  | 
module.exports 可以通过赋值的方式暴露变量, exports不行
1  | module.exports = {  | 
模块分成两大类
- 核心模块
- node引擎提供的模块
 - 核心模块的标识, 就是模块的名字
 
 - 文件模块
- 用户自己创建的模块
 - 文件模块的标识, 是文件袋路径
 
 
在全局中创建的变量函数都会作为global的属性属性或者方法保存
1  | a = 10;  | 
当node执行模块中的模块时, 会在代码最顶部添加一行代码
1  | function(exports,require, module, _filename, _dirname){  | 
exports
- 将变量暴露到外部
 
require
- 引入外部模块
 
module
- 模块本身
 - exports就是module的属性
 
__filename
- 文件绝对路径
 
__dirname
- 文件夹路径
 
package
包, 实际上是一个压缩文件, 解压后为原目录.
由包结构和包描述文件组成
符合规范的目录包含以下文件:
- package.json — 必须的描述文件
 - bin - 可执行的二进制文件
 - lib - js代码
 - doc - 文档
 - test - 单元测试
 
WebStrom自动生成的文件package.json
1  | {  | 
包描述文件用于表达非代码相关的信息, 是一个JSON文件
不可以在里面写注释
NPM
Node Package Manager
NPM帮助Node完成了第三方模块的发布安装和依赖
npm search 搜索
1  | npm search math  | 
npm init
可以创建一个package.json
npm install
1  | npm install math  | 
npm其他命令
- npm -v
 - npm version
 - npm remove/r 包名
 - npm install 包名–save 安装包并添加依赖
 - npm install 不加包名, 下载当前项目依赖的包
 - npm install 包名 -g 全局安装包 (全局安装包一般都是一些工具)
 
淘宝npm镜像
1  | npm install -g cnpm --registry=https://registry.npm.taobao.org  | 
Buffer
结构和数组很像, 操作的方法也和数组类似
专门用来存二进制数据
不需要引入模块, 可以直接使用
每个数据都是二进制, 但是显示的时候都是十六进制
buffer中一个元素, 占用一个字节Byte – 8bit
buffer 大小, 一但确定不再修改
- 因为buffer实际上是对底层内存的直接操作
 
1  | var str = "Hello";  | 
创建指定大小的buffer
buffer所有构造函数都不推荐使用
1  | var buf2 = new Buffer(10); //10个字节的buffer  | 
通过索引操作buffer中的元素
1  | var buf2 = Buffer.alloc(10);//10个字节的buffer  | 
File System
fs模块
1  | var fs = require("fs");  | 
同步和异步调用
- 同步会阻塞程序运行
 - 异步不会阻塞程序运行
 
同步文件写入
1  | var file = fs.openSync(path, flags[, mode])  | 
- path 要打开的文件路径
 - flags 要做的操作运行
- 读写, 只读, 只写
 - r , w
 
 - mode 设置文件操作权限, 一般不传
 
方法返回一个文件描述符作为结果, 可以通过描述符文件对文件进行各种操作
1  | fs.write(fd, string[, position[, encoding]])  | 
- fd 文件描述符, 需要传递要写入文件的描述符
 - string 需要写入的内容
 
1  | fs.closeSync(fd)  | 
关闭文件
异步写入文件
1  | fs.open("hello.txt","w",function(){  | 
没有返回值, 但是有回调函数
- 结果都是通过回调函数的参数返回, 参数有: 
- err 错误
 - fd 文件描述符
 
 
异步写入
1  | fs.open("hello.txt","w",function(err, fd){  | 
简单的文件写入
1  | fs.writeFile(file, date[, options], callback)  | 
- file 文件名
 - data
 - opions
 - callback 回调函数
 
1  | var fs = require("fs");  | 
默认情况下, 覆盖原文件内容
追加内容到flags
- a 打开文件用于追加, 没有则创建
 
1  | fs.writeFile("hello.txt", "something",{flag:"a"}, function(err){  | 
流式文件写入
普通写入不适合大文件写入, 性能较差, 容易导致内存溢出
创建一个可写流
1  | fs.createWriteStream(path[, options])  | 
- path 文件路径
 - options 配置都参数
 
1  | var ws = fs.createWriteStream("hello4.txt");  | 
1  | ws.wirte("wirte something");  | 
可以持续写入
可以通过监听流的open和close事件来监听流的打开和关闭
1  | ws.on("open", function(){  | 
关闭要用end不能用close
1  | ws.end();  | 
简单文件读取
1  | fs.readFile("an.jpg", function(err,data){  | 
流式文件读取
1  | var rs = fs.createReadStream("an.jpg");  | 
如果读取通过可读流读取数据, 必须绑定一个data事件, 绑定完毕, 会自动开始读取数据
数据为回调函数
1  | var ws = fs.createWriteStream(a.mp3);  | 
更简单的方法
1  | rs.pipe(ws);  | 
pipe可以直接将可读流中的内容直接输出到可写流中;
其他file方法
fs.exits(path, callback);
fs.stat();
- 返回一个对象, 有对象状态相关信息
 
fs.unlink(path, callback)
- 删除文件
 
fs.readdir(“.”, function(err, files){})
- files 是文件数组
 
fs.truncateSync(“hello.txt”, 10)
- 截断文件, 设置文件成指定大小
 
fs.mkdir(path[, mode], callback)
- 创建目录
 
fs.rmdir(path[, mode], callback)
fs.rename(oldPath, newPath, callback)
- 重命名
 - 也可以间接实现剪切操作
 
fs.watchFile(filename[, options], listener)
- 监视文件的修改
 - 参数: 
- filename
 - options
 - listener 回调函数, 文件发生时, 函数会被执行
- 有两个参数:
 - curr
 - prev
 - 都是stats对象