1、JS运行环境:
前端浏览器环境:V8引擎解析执行、浏览器所提供的API调用
Node.js后端环境(基于V8引擎的JS运行环境):V8引擎、API(他不是浏览器环境,所以无法调用web的dom和bom)
2、 JS学习:JS语法+DOM+BOM+第三方库(jq等)
Node学习:JS语法+Node模块(fs、path、http等)+第三方库(express等)
3、fs文件系统模块:
fs.readFile(path路径, option可选编码参数, callback回调函数,包含data和err)
fs.writeFile(path路径, data内容, option可选编码参数, callback回调函数,包含data和err)
IO操作为宏任务,若同时存在write和read并操作同一文件,先执行write:
const fs = require("fs") //IO读取是宏任务,在main、micro打印之后 fs.readFile("./1.txt","utf8",function(err, dataStr){ if (err) { return console.log(err); } console.log(dataStr); }) new Promise((resolve, reject)=>{ resolve() }).then(()=>{ console.log("micro"); }) console.log("main"); fs.writeFile("./1.txt","helloNode1",function(err, dataStr){ if (err) { return console.log(err); } console.log(dataStr); }) //main //micro //undefined //helloNode1
路径错误指的是在执行js的时候用node .\目录\js文件运行时,js文件内的路径调用处于不同层路径,导致调用失败。
使用绝对路径,但是移植性差,不利于后期维护
使用__dirname解决,表示当前文件所处的目录
fs.readFile(__dirname+"/1.txt","utf-8",(err, dataStr)=>{ if (err) { return console.log(err.message); } console.log(dataStr); })
4、path路径模块
path.join([...path路径片段]) 返回拼接好的字符串,相比于+号,他会自动处理一些不必要的错误,比如./和/
path.basename(path路径, option可选后缀,如果加上,返回的文件名就不带后缀)
path.extname(path路径),返回扩展名
5、http模块:创建web服务器
const http = require("http") //实例化服务器 const server = http.createServer() //服务器绑定request事件 server.on('request',(req, res)=>{ //若有客户端请求,则内容触发 console.log("服务器收到请求"); }) //启动服务器 server.listen(80,()=>{ console.log("服务器启动成功"); })
req(request):请求对象,访问与客户端相关的数据或属性,如req.url、req.method等
res(respond):响应对象,返回响应内容,并结束本次处理过程,如res.end()
//服务器绑定request事件 server.on("request", (req, res) => { //若有客户端请求,则内容触发 console.log(req.method, req.url); let content = "404"; //动态路由Î if (req.url === "/" || req.url === "/index.html") { content = "中国"; } //响应,如数据,html等 //防止中文乱码,要在响应头加上格式 res.setHeader("Content-Type", "text/html; charset=utf-8"); res.end(content); });
6、模块化
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。
把代码进行模块化拆分的好处:
1、规范:比如如何引用;如何暴露
2、模块分类:
3、加载模块:require() 加载的时候会执行里面的代码,其可以省略.js后缀名
4、模块作用域:在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问。防止变量污染,命名冲突等
5、Module对象,里面存储了和当前模块有关的信息
暴露:module.exports { },将模块内的成员共享出去,供外界使用。其以module.export所导出的对象为准(为了简化,写exports也可以,他们初始指向同一个堆,但是要注意直接赋值的时候堆的转换,最终以module.exports为准,还要注意exports最为最后一个对象时,是无法输出的)
exports.age = 20 //此时module.exports和exports都为age=20 module.exports.name = "jacky" //此时module.exports和exports都指向age=20, name=jacky的堆 module.exports = { name: "JJ" //最终导出,此时module.exports指向另一个堆 } exports = { gender: male //exports是无法作为最终输出的,所以这行无效。除非下面加上module.exports = exports输出 }
6、node遵循了 CommonJS 模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖
7、npm(包管理)和包(第三方模块,其也是基于内置模块开发出来的)
npm:node_modules 文件夹用来存放所有已安装到项目中的包。
package-lock.json 配置文件用来记录 node_modules 目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等
1、 @ 符号安装指定具体的版本
2、版本号规范:例如 2.24.0
3、package.json包管理配置文件
记录项目的名称、版本号、描述等,项目中都用到了哪些包,哪些包只在开发期间会用到,那些包在开发和部署时都需要用到
在上传项目时,由于node_modules文件夹过大,一般会在.gitignore中忽略上传,他人通过package.json去下载对应的包
其中必须包含 name,version,main 这三个属性,分别代表包的名字、版本号、包的入口
npm init -y直接生成该默认文件,如果不-y则需要配置文件如版本,名称等。路径不能中文。
4、包分类
5、开发自己的包:
package.json包管理(main/version/main/decription描述/keywords数组,提供搜索关键字)、index.js包入口、README.md说明文档
模块拆分:在 index.js 中,导入两个模块,得到需要向外共享的方法并使用 module.exports 把对应的方法共享出去(展开)
// 这是包的入口文件 const date = require('./src/dateFormat') const escape = require('./src/htmlEscape') // 向外暴露需要的成员 module.exports = { ...date, ...escape }
8、模块加载机制
1、模块优先从缓存中加载,提高加载效率,require只会执行一次
2、内置模块加载优先级最高,同名优先加载内置,一般也不会有和内置模块名相同的包
3、使用 require() 加载自定义模块时,必须指定以 ./ 或 ../ 开头的路径标识符,否则会认为是第三方或内置模块
4、如果省略文件后缀,会按顺序查找加载:
5、第三方模块加载机制:如果当前路径的node_module没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录
6、目录作为加载模块:先找package.json,然后找里面的main;如果没有,就找index.js
9、其他一些内置模块:
1、events:事件常用方法
const EventEmitter = require("events"); // 1.创建事件发射器 const emitter = new EventEmitter(); // 2.监听某一个事件 // addListener是on的alias简写 emitter.on('click', (args) => { console.log("监听1到click事件", args); }) const listener2 = (args) => { console.log("监听2到click事件", args); } emitter.on('click', listener2) // 3.发出一个事件以及取消该事件 setTimeout(() => { emitter.emit("click", "coderwhy", "james", "kobe"); emitter.off("click", listener2); emitter.emit("click", "coderwhy", "james", "kobe"); }, 2000);
2、until:工具
util.format(格式化输出字符串); util.isArray(检查是否为数组); util.RegExp(是不是正则); util.isDate(是不是日期型); util.inherits(child, parent)实现继承;