NodeJS
NodeJS是一个能够在服务器端运行JavaScript的开放源代码、跨平台JavaScript运行环境
模块化
ESMAScript标准缺陷:没有模块系统、标准库较少、没有标准接口、缺乏管理系统
CommonJS
-
CommonJS规范
- CommonJS规范的提出,主要是为了弥补当前JavasScript没有标准的缺陷。
- CommonJS规范为JS指定了一个美好的愿景,希望JS能够在任何地方运行。
- CommonJS对模块的定义十分简单
- 模块引用
- 模块定义
- 模块标识
-
模块化的引用
- 使用
require()
函数来引入一个模块 - 例子:
var 变量名 = require("模块的标识")
- 使用
-
模块化的定义
-
在node中,一个js文件就是一个模块
-
在node中,每一个js文件中的js代码都是独立运行在一个函数中
- 外部的模块无法访问
-
在node中有一个全局变量global,作用和网页中window类似
- 在全局中创建的变量都会作为global的属性保存
-
在全局中创建的函数都会作为global的方法保存
-
当node在执行模块中的代码时,它会在代码外套一层函数,因此模块中的代码其实都是包装在一个函数中执行的
function(exports, require, module, __filename, __dirname) {}
exports - 该对象用来将变量或函数暴露到外部 require - 函数,用来引入外部的模块 module - module代表的是当前模块本身 - exports就是module的属性 module.exports === exports // true __filename - 当前模块的完整路径 __dirname - 当前模块所在文件夹的完整路径
-
导出变量和函数
- 通过exports只能使用
.
的方式来向外暴露内部变量exports.属性 = 属性值
exports.方法 = 函数
- module.exports既可以通过
.
的形式,也可以直接赋值module.exports.属性 = 属性值
module.exports.方法 = 函数
module.exports = 对象
// helloModule下 // 情况1 exports = { name: 'Tom' } // 情况2 module.exports = { name: 'Tom' } // testModule下 var hello = require("./helloModule"); console.log(hello.name); // 情况1: undefined // 情况2: Tom // 本质: 指针指向内存问题
- 通过exports只能使用
-
-
模块的标识
- 模块的标识就是模块的名字或路径
- 核心模块
- 由node引擎提供的模块
- 核心模块的标识就是模块的名字
- 文件模块
- 由用户自己创建的模块
- 文件模块的标识就是文件的路径(绝对路径、相对路径)
包
CommonJS的包规范允许我们将一组相关的模块组合到一起,形成一组完整的工具
CommonJS的包规范由包结构和包描述文件组成
-
包结构
- 用于组织包中的各种文件
- package.json 包描述文件(*必须) - bin 可执行二进制文件 - lib js代码 - doc 文档 - test 单元测试
-
包描述文件
- 描述包的相关信息,以供外部读取分析
- 字段:name、description、version、keywords、maintainers、contributors、bugs、licenses、repositories、dependencies、homepage、os、cpu、engine、builtin、directories、implements、scripts、author、bin、main、devDependencies
NPM
Node Package Manager
对于Node而言,NOM帮助其完成了第三方模块的发布、安装和依赖等。借助NPM,Node与第三方模块之间形成了很好的一个生态系统。
- npm的命令
npm -v
查看npm的版本npm version
查看所有模块的版本npm search [包名]
搜索包npm install [包名]
安装包npm remove [包名]
删除包npm install [包名] --save
安装包并添加到依赖中*npm inatll
下载当前项目所依赖的包npm install [包名] -g
全局安装包(一般都是一些工具)
Buffer
- Buffer的结构和数组很像,操作的方法也和数组类似
- 数组中不能存储二进制文件,而Buffer就是专门用来存储二进制数据
- 使用Buffer不需要引入模块,直接调用即可
- Buffer中存储的都是二进制数据,显示时以16进制的形式显示(短)
- 每一个元素的取值范围是
00 - ff
,即0 - 255
- 每一个元素的取值范围是
- Buffer的大小一旦确定,则不能修改,Buffer实际上是对底层内存的直接操作
let str = "Hello 南京"
let buf = Buffer.from(str) // 将字符串转换为Buffer
console.log(str.length, buf.length) // 8 12 字符串长度 占内存的大小
console.log(buf.toString()) // "Hello 南京"
// 创建指定大小的Buffer
let buf = Buffer.alloc(10) // 创建一个指定大小的Buffer
// 通过索引来操作buf中的元素
buf[0] = 88 // 0x58
buf[1] = 0xaa // 0xaa
buf[2] = 556 // 2c 1000101100 -> 00101100
buf[10] = 15 // 没有变化
console.log(buf[2]) // 170 显示时输出一定是10进制
console.log(buf[1].toString(16)) // aa
let buf = Buffer.allocUnsafe(10) // 不清空内存原有数据,优点是性能好
文件系统
文件系统简单来说就是通过Node来操作系统中的文件
- fs模块中所有操作都有两种形式可供选择同步和异步。
- 异步文件操作
- 异步文件打开
fs.open(path, flags[, mode], callback(err, fd))
- 异步文件打开
'a': 打开文件用于追加。 如果文件不存在,则创建该文件。
'ax': 类似于 'a',但如果路径存在,则失败。
'a+': 打开文件用于读取和追加。 如果文件不存在,则创建该文件。
'ax+': 类似于 'a+',但如果路径存在,则失败。
'as': 打开文件用于追加(在同步模式中)。 如果文件不存在,则创建该文件。
'as+': 打开文件用于读取和追加(在同步模式中)。 如果文件不存在,则创建该文件。
'r': 打开文件用于读取。 如果文件不存在,则会发生异常。
'r+': 打开文件用于读取和写入。 如果文件不存在,则会发生异常。
'rs+': 打开文件用于读取和写入(在同步模式中)。 指示操作系统绕过本地的文件系统缓存。
'w': 打开文件用于写入。 如果文件不存在则创建文件,如果文件存在则截断文件。
'wx': 类似于 'w',但如果路径存在,则失败。
'w+': 打开文件用于读取和写入。 如果文件不存在则创建文件,如果文件存在则截断文件。
'wx+': 类似于 'w+',但如果路径存在,则失败。
- 流式文件操作
- 同步、异步、简单文件的写入都不适合大文件的写入,性能较差,容易导致内存溢出
// 文件写入
let fs = require("fs");
// 同步文件写入
let fd = fs.openSync("hello1.txt", "w");
fs.writeSync(fd, "今天天气真不错~");
fs.closeSync(fd);
// 异步文件写入
let fd = fs.open("hello2.txt", "w", function (err, fd) {
if (!err) {
fs.write(fd, "异步写入内容~~~", function (err) {
if (!err) {
console.log("写入成功!");
}
fs.close(fd, function (err) {
if (!err) {
console.log("文件已关闭!");
}
})
})
} else {
console.log(err);
}
});
// 简单文件写入
fs.writeFile("hello3.txt", "这是通过writeFile写入的内容", {flag: "w"}, function (err) {
if (!err) {
console.log("写入成功!");
}
});
// 流式文件写入
let ws = fs.createWriteStream("hello4.txt");
ws.once("open", function () {
console.log("流打开了~~~");
});
ws.once("close", function () {
console.log("流关闭了~~~");
});
ws.write("通过可写流写入文件的内容1!");
ws.write("通过可写流写入文件的内容2!");
ws.end(); // 关闭流
let fs = require("fs");
// 简单文件读入
fs.readFile("hello.txt", function (err, data) {
if (!err) {
console.log(data);
}
});
// 流式文件读入
let rs = fs.createReadStream("hello.txt");
rs.once("open", function () {
console.log("可读流打开了~~~");
});
rs.once("close", function () {
console.log("可读流关闭了~~~");
});
rs.on("data", function (data) {
console.log(data);
});
// 流式文件读取并写入
let rs = fs.createReadStream("hello.txt");
let ws = fs.createWriteStream("hello1.txt");
rs.pipe(ws);