Node.js 第三天课程笔记
反馈
- 推荐 sublime 插件
- 写代码用面向对象写还是模块化写
- 封装、继承、多态
- 命名冲突、文件依赖
- SeaJS 和 jQuery 有什么区别?
- 要从两个技术要解决的问题的角度思考他们的区别
- require 加载规则
- 好多快捷键不知道怎么按的
- 模块标识与静态资源路径
- filereader
- 异步的读取存储在用户计算机上的文件
- 可以使用File对象或者Blob对象来指定所要处理的文件或数据
- File对象可以是来自用户在一个元素上选择文件后返回的FileList对象
- 同步异步
- 知识脑图
- 如何使用web技术构建客户端应用程序
- 复制文件案例
- node 能不能像 PHP 那样可以做个完整的后台
- 对于 node 在项目中的职责
- 充当的是服务器端
复习
全局成员
模块系统
模块基本特性
- 一个单独的文件就是一个模块,每一个模块都是一个单独的作用域
- 每个文件的对外接口是
module.exports
对象,该对象就是模块内部与外部通信的桥梁- 模块与模块之前通信的桥梁
- 为了方便,Node为每个模块提供一个
exports
变量,指向了module.exports
- 在对外输出模块接口时,可以向 exports 添加属性,就相当于为 module.exports 添加了属性
- 不能直接将 exports 指向一个值,这样会切断
exports
和module.exports
之间的引用关系 - 如果一个模块的对外接口是一个单一的值,不能使用
exports
,只能使用module.exports
-
require
方法用于在其它模块加载module.exports
接口对象 - 模块可以被多次加载,但是只会在第一次加载的时候运行一次,然后被缓存、
- 目的是为了提高性能(因为加载就需要时间)
- 模块加载的顺序是同步进行(SeaJS中是预加载,懒执行)
- node 是在执行到 require 的时候,才去同步的加载该文件模块(读取文件)
- node 是按照代码出现的顺序进行加载
- node 的代码运行在服务器端,需要考虑用户吗》?
- seajs 中是 育新加载好所有的 js 文件(不执行),等到所有的js文件都加载完毕了,才开始执行
- seajs 是预加载,懒执行(某一个文件加载成功之后并没有立即执行)
- seajs 预加载是为了防止在代码中出现动态加载而导致功能无法执行或者延迟执行
- 思考 node 中的同步加载和 前端浏览器中的 预加载(异步并行)
require 加载规则
文件模块(用户编写)和核心模块(node原生提供的)
- 以
/
开头的绝对路径文件模块- 在 Windows 中, 以 '/' 开头的模块标识,默认去 当前文件所属的 盘符 根路径 下找
- 以
./
或../
开头的相对路径文件模块- 相对路径永远是相对于 require 方法出现的代码文件
- 不以
./
或../
或/
开头的核心模块- 核心模块本质上还是文件模块,所以可以在源码中找到核心模块文件
- 模块标识可以省略后缀名,Node会按照
.js
、.json
、.node
进行查找加载-
.js
文件会以 js 脚本进行解析 -
.json
会以 JSON 格式文本进行解析 -
.node
会以编译后的二进制文件进行解析
-
模块的循环加载
如果发生循环加载,循环的模块加载会得到不完整的接口数据。 以后写代码,最好不要循环加载模块(没有意义)
require 得到的是输出的值的拷贝
自己手写实现 myRequire *
在模块中,一旦输出一个值,模块内部的变化就影响不到这个值
文件操作
why what how when where
同步和异步
异步编程
异步操作的嵌套会越来越深,如何解决这个问题,promise可以用来解决 fs.readFile('',function(err,data){ fs.readFile('',function(err,data){ fs.readFile('',function(err,data){ fs.readFile('',function(err,data){
})
})
}) })
什么是同步
什么是异步
同步代码如何处理异常
写一个方法,该方法可以将一个 json 格式的字符串转换为 JSON 对象
异步代码如何处理异常
回调函数的设计
- 回调函数作为参数的最后一个参数出现
- 第一个参数默认接收错误信息
- 第二个参数才是真正的数据
-
强调错误优先
- 回调函数第一个参数为上一步错误信息
- 通过在回调函数中判断err是否为null来检测异步操作过程是否出错
Buffer缓冲区
Buffer对象是Node.js用来处理二进制数据的一个接口 Buffer是Node原生提供的全局对象,可以直接使用,不需要
require
文件读取的两个问题: 二进制数据 乱码
为什么要操作二进制数据?
一旦要操作文件和在网络中传递数据,就一定要了解如何处理二进制数据
ASCII 是计算机早期的一种字符编码
随着计算机的不断的发展,进入了全世界各个国家,由于各个国家对应的语言不一致, 为了更快的普及,ASCII 已经不能满足世界各地对语言的需求 所以,各个国家针对于自己的语言制定了不同的字符编码 (字符到二进制之间的转换关系,实际上就是一本字典)
中国(gbk字符编码使用的居多)
韩国()
晓明(使用的支持中文的操作系统):发送了一个 gbk 编码的文件 baby(使用的支持韩文的操作系统):把 gbk 编码当成韩文编码进行解析
学习目标
- 了解什么是编码,为什么要有编码
- 因为计算机只能识别0或者1,而且只能存储0或者1
- 为了把人类能识别的字符存储到计算机中,所以人类制造了一个字典
- 那么这个字典就是 人类能识别的字符 到 计算机能识别的二进制数据 之间的转换
- 掌握buffer和字符串之间的转换
- 通过调用 buffer实例对象的 toString() 方法就可以将buffer转换为字符
- 掌握如何拼接buffer对象
- 可以使用Buffer的类方法 concat 将多个 buffer 对象拼接为一个完整的 buffer 对象
二进制和编码
Buffer支持的编码
Buffer构造方法
- new Buffer(size)
- new Buffer(str[, encoding])
Buffer的实例属性
- buf.length
- 注意一定要会区分字符串的length和buf的length
Buffer的实例方法
- buf.write()
- buf.toString() 将一个buffer二进制对象转换为字符,默认编码就是 utf8
Buffer的类方法
- Buffer.isEncoding()
- 用来判断是否支持该编码类型
- Buffer.isBuffer()
- 用来判断一个对象是否是buffer类型对象
- Buffer.byteLength()
- 用来计算一个字符串对应的编码所占用的字节大小
- Buffer.concat()
- 可以将多个 buffer 对象拼接为一个完整的buffer对象
path模块
在文件操作的时候,经常会遇到路径拼接的问题, 例如:读取一个路径中的文件名部分,或者说获取一个路径中的后缀名部分 获取把两个不完整的路径拼接为一个完整的路径
文件相关操作API
- 读取文件
- 写入文件
- 向文件中追加内容
- 获取文件信息 stat
- 删除文件
- 验证路径是否存在
- 重命名文件
- 移动文件
- 监视文件变化