第二章 常用模块(一)
Module
JavaScript的模块规范:
CommonJS
:将每个文件看成一个模块,模块内部定义的变量都是私有
的,无法被其他模块使用,除非使用预定义的方法将内部变量暴露出来(通过exports
和require
关键字来实现)。最出名的实现就是Node.js
,特点就是模块的加载是同步
的。AMD
(Asynchronous Module Definition):采用异步方式
加载模块,模块的加载不影响它后面的语句的运行。依赖这个模块的代码定义在一个回调函数中,等加载完成后,这个回调函数才会运行。RequireJS
就是AMD规范的实现。- ES6提出的模块机制。
require及其运行机制
使用require
关键字来加载模块
var person = require("./person.js");
可以只导入模块的一部分属性,并且require关键字并不依赖与exports。
重复引入
:Node默认先从缓存
中加载模块,一个模块被第一次加载后,就会在缓存中维持一个副本,如果遇到重复加载的模块会直接提取缓存中的副本。require的缓存策略
:基于文件路径
定位的。
为什么在Node,js中,require()加载模块是同步而非异步?
遵守了CommonJS
标准;模块的个数往往有限,Node会自动缓存
已经加载的模块,再加上访问的都是本地文件,产生的IO开销几乎可以忽略;Node运行在服务端
,很少遇到重启服务的情况,在服务启动时在加载上花点时间也没什么影响。
require的隐患
加载一个模块相当于执行模块内部的代码,所以对引用未知的模块保持警惕,可能导致严重的内存泄露。
模块化与作用域
在Node repl
环境中控制台的全局this
和global
可以看作是同一对象,而在脚本文件中,二者并不等价
。
脚本文件中定义的全局this
指向module.exports
。
Node中的作用域种类(脚本文件):
全局作用域
:没有用var、let或const之类的关键字修饰的变量隶属于全局作用域,可以通过global
对象访问到。模块作用域
:在代码文件顶层(不在任何方法、对象中)使用var、let或const修饰的变量都位于模块作用域中,this指向module.exports。函数作用域
块级作用域
:let关键字;
Buffer
Buffer是Node特有的数据类型,主要用来处理二进制数据
。
在文件操作和网络操作中,如果不显式声明编码格式,其返回数据的默认类型就是Buffer
。
Buffer的构建和转换
可以使用Buffer类直接初始化一个Buffer对象,参数可以是由二进制组成的数组。
new Buffer()方法不推荐使用,官方推荐使用Buffer.from方法
来初始化一个Buffer对象。
把一个Buffer对象转成字符串形式
,需要使用toString
方法:
buffer.toString([encoding],[start],[end])
encoding - 目标编码格式
start - 开始位置
end - 结束位置
buffer支持的编码类型种类:ASCII、Base64、Binary、Hex、UTF-8、UTF-16LE/UCS-2;
buffer还提供了isEncoding
方法来判断是否支持转换为目标格式。
Buffer拼接官方推荐使用push
方法来拼接Buffer
;
File System
File System
是Node中使用最为频繁的模块之一,该模块提供了读写文件的能力
,是借助于底层的linuv的C++API实现的。
常用的API:
readFile
:异步读取文本文件中的内容,会将文件全部内容都读到内存中,适用于体积较小的文本文件;大文件建议选择stream
;readFile
读出的数据需要在回调方法中获取,而readFileSync
直接返回文本数据内容。writeFile
:第一个参数为文件名,如果不存在则会尝试创建它;fs.stat(path, callback)
:用来获取文件的状态,可以用来判断文件是否存在。和fstat
的区别在于fstat方法第一个参数是文件描述符,可以和open
方法配合使用,因为open方法返回的结果就是一个文件描述符。