Node.js的模块化
Node用于是由模块组成的,遵循的是CommonJs模块的规范。
1.什么是CommonJs规范
CommonJs是一套代码规范,目的是为了构建JavaScript在浏览器之外的生态系统(服务器端,桌面端)。
JavaScript 诞生之初只是为了写网页小脚本, 并不作为开发大型复杂应用的语言, 其自身有很多不足. 并且, 官方规范 (ECMAScript) 制定的时间较早, 涵盖范围较小, 对于后端开发而言, 例如文件系统, I/O 流, 模块系统, 等等方面都没有相应的标准. 基于种种的不足, CommonJS 规范致力于弥补 JavaScript 没有标准的缺陷, 让 JavaScript 有能力去开发复杂应用, 同时具备跨平台能力.
通过该规范使JavaScript具备开发复杂应用和跨平台的能力。
2.CommonJs规范的主要内容
导出模块:module.exports 导出模块
导入模块:require("模块名称")
3.CommonJs模块的特点
- 所有代码运行在当前模块作用域中,不会污染全局作用域
- 模块同步加载,根据代码中出现的顺序依次加载
- 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
4.示例
(1)整体导出一个类
在demo.js文件中:
class Person {
constructor(name,age){
this.name = name;
this.age = age;
}
getName = function(){
console.log("姓名:",this.name);
}
getAge = function(){
console.log("年龄:",this.age);
}
}
module.exports = Person;
在test.js文件中:
const Person = require("./demo");
const p1 = new Person("刘备",36);
const p2 = new Person("关羽",29);
p1.getName();
p1.getAge();
(2)一般导出
在demo.js文件中:
module.exports.name = "xian";
module.exports.age = 78;
module.exports.getName = function(){
console.log("姓名:",this.name);
}
module.exports.getAge = function(){
console.log("年龄:",this.age);
}
在test.js文件中:
const person = require("./demo");
person.getName();
person.getAge();
module对象
每个导出的模块都有一个module
对象,该对象包含的属性有:
1.module.exports
module.exports:表示当前模块对外输出的接口,其他模块引用的都是module.exports导出的变量。
2.exports
exports变量:指向module.exports,目的是为了操作的方便。它不能直接指向一个值。
require
使用require
导入模块:导入并执行一个JavaScript
文件,返回的是一个exports
对象,若没有找到相应的对象就会报错。
(1)模块输出的是一个函数,则该函数的输出接口不能用exports变量来导出,必须用module.exports来导出。
(2)加载规则
1.用来加载js文件,默认的文件扩展名为.js。
2.根据参数的不同格式,去不同路径下查找相应的js文件
“/”:表示加载路径是绝对路径(从根目录开始的路径)
“./(…/)”:表示加载路径是相对路径
其它:表示加载的模块是node的核心模块。
Buffer对象
Buffer对象:是一个Node中的全局对象,可以直接使用,不需要require导入。该对象提供了在Node中处理二进制数据的接口。
JavaScript比较擅长处理字符串,对于处理二进制数据(比如TCP数据流),就不太擅长。Buffer对象就是为了解决这个问题而设计的。它是一个构造函数,生成的实例代表了V8引擎分配的一段内存,是一个类似数组的对象,成员都为0到255的整数值,即一个8位的字节。
用来弥补JavaScript在二进制数据处理上的不足。
Buffer本身是一个构造函数(类),Buffer对象是V8引擎分配的一段内存,格式类似数组,每个单元就是一个字节,存放的是0~255之间的数据。
Buffer的基本操作
(1)创建:
let bytes = new Buffer(size);
//生成一个256字节的Buffer示例
var bytes = new Buffer(256);
//遍历每个字节,写入内容
for(var i=0;i<bytes.length;i++){
bytes[i] = i;
console.log(bytes[i]);
}
(2)切片:
bytes.slice(start,end);
//生成一个256字节的Buffer示例
var bytes = new Buffer(256);
//遍历每个字节,写入内容
for(var i=0;i<bytes.length;i++){
bytes[i] = i;
console.log(bytes[i]);
}
//切片处理
let end = bytes.slice(240,256);
console.log(end); //输出结果为:<Buffer f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff> 结果为16进制数
console.log(end[0]); //输出结果为:240
(3)拷贝
bytes.copy(目标缓冲区,目标缓冲区的起始位置,源缓冲区的起始位置,源缓冲区的结束位置)
var bytes = new Buffer(8);
for(var i=0;i<bytes.length;i++){
bytes[i] = i;
}
var more = new Buffer(4);
bytes.copy(more,0,4,8);
console.log(more); //输出结果为:<Buffer 04 05 06 07>
console.log(more[3]); //输出结果为7
console.log(more[0]); //输出结果为4
(4)Buffer和字符串的互相转换
Buffer和字符串之间的转换:支持的编码格式(ascii码、utf8)
(5)Buffer和二进制数组的区别
二进制数组:
Int8Array:-128~127
UintArray:0~255
Int16Array:-32768~32767
UInt16Array:0~65535
Buffer类
Buffer类是基于Uint8Array的,因此其值为0~255的整数数组。
//创建一个长度为10的零填充缓冲区
const buf1 = Buffer.alloc(10);
//创建一个长度为10的填充0x1的缓冲区
const buf2 = Buffer.alloc(10,1);
/* 创建一个长度为10的未初始化缓冲区,这比调用alloc()更快但返回了缓冲区实例
但有可能包含旧数据,可以通过fill()或write()来覆盖旧值
*/
const buf3 = Buffer.allocUnsafe(10)
//创建包含[0x1,0x2,0x3]的缓冲区
const buf4 = Buffer.from([1,2,3]);
console.log(buf4)
//创建包含UTF-8字节的缓冲区[0x74、0xc3、0xa9、0x73、0x74]
const buf5 = Buffer.from('test');
console.log(buf5)
//创建一个包含Latin-1
const buf6 = Buffer.from('abc','latin1')
console.log(buf6)
Buffer构造函数
// 参数是整数,指定分配多少个字节内存
var hello = new Buffer(5);
// 参数是数组,数组成员必须是整数值
var hello = new Buffer([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
console.log(hello.toString())
// 参数是字符串(默认为utf8编码)
var hello = new Buffer('Hello');
hello.length // 5
hello.toString() // "Hello"
// 参数是字符串(不省略编码)
var hello = new Buffer('Hello', 'utf8');
// 参数是另一个Buffer实例,等同于拷贝后者
var hello1 = new Buffer('Hello');
var hello2 = new Buffer(hello1);