引言
💥为什么JavaScript
可以在浏览器中执行?
不同的浏览器使用不同的JavaScript
解析引擎
Chrome浏览器 = > V8
💥为什么JavaScript
可以操作DOM
和BOM
?
每个浏览器都内置了DOM
,BOM
这样的API
函数,因此,浏览器中的JavaScript
才可以调用他们
💥浏览器中的javaScript
运行环境
运行环境是指代码正常运行所需的必要环境
总结:
-
v8
引擎负责解析和执行JavaScript
代码 -
内置
API
是由运行环境提供的特殊接口,只能在所属的运行环境中被调用
一.Node.js
1.1什么是Node.js
Node.js
是一个基于Chrome V8
引擎的JavaScript
运行环境
Node.js
中的JavaScript
运行环境
注意:
- 浏览器是
JavaScript
的前端运行环境 Node.js
是JavaScript
的后端运行环境Node.js
中无法调用DOM
和BOM
等浏览器内置API
二.Node.js
可以做什么
Node.js
作为一个javaScirpt
的运行环境,仅仅提供了基础的功能和API
然而,基于Node.js
提供的这些基础使很多强大的工具和框架层出不穷
- 基于
Express
框架,可以快速构建Web
应用 - 基于
Electron
框架,可以构建跨平台的桌面应用 - 基于
restify
框架,可以快速构建API
接口项目
三.Node.js
学习路径
JavaScript
基础语法 + Node.js
内置API
模块(fs
,path
,http
等)+ 第三方API
模块(express
,mysql
)等
四.fs
文件系统模块
4.1什么是fs
文件系统模块
fs
模块是Node.js
官方提供的,用来操作文件的模块
提供了一系列的方法和属性,用来满足用户对文件的操作需要
例如:
fs.redFile()
方法,用来读取指定文件中的内容
fs.writeFile()
方法,用来向指定的文件中写入内容
如果要在JavaScript
代码中,使用fs
模块来操作文件,则需要使用如下的方式先导入它:
const fs = require('fs')
4.2读取指定文件中的内容
4.2.1fs.readFile()
的语法格式
使用fs.readFile()
方法,可以读取指定文件中的内容
fs.readFile(path[,options],callback);
参数解读:
path:必选参数,字符串,表示文件的路径
options:可选参数,表示以什么编码格式来读取文件
callback:必选参数,文件读取完成后,通过回调函数拿道读取的结果
5.4.2fs.readFile()
的示例代码
以utf8
的编码格式,读取指定文件的内容,并打印err
和dataStr
的值
const fs = require('fs')
fs.readFile('./files/11.txt','utf8',function(err,dataStr){
console.log(err)
console.log('----')
console.log(dataStr)
})
4.2.3判断文件是否读取成功
const fs = require('fs')
fs.readFile('./files/1.txt','utf8',function(err,result){
if(err){
return console.log('文件读取失败!'+err.message);
}
console.log('文件读取成功,内容是'+result);
})
4.3向指定的文件中写入内容
4.3.1fs.writeFile()
语法格式
fs.writeFile(path,data[,options],callback)
参数解读:
path:必选参数,字符串,表示文件的路径
data:必选参数,表示要写入的内容
options:可选参数,表示以什么编码格式来读取文件
callback:必选参数,文件读取完成后,通过回调函数拿道读取的结果
4.3.2fs.writeFile()
的示例代码
const fs = require('fs')
fs.writeFile('./files/2.txt','Hello Node js!',function(err){
console.log(err)
})
4.4fs
模块-路径动态拼接的问题
在使用fs
模块操作文件时,如果提供的操作路径是以./或…/开头的相对路径时,很容易出现路径动态拼接错误的问题
原因:代码在运行的时候,会以执行node命令时所处的目录,动态拼接出被操作文件的完整路径
解决1:不使用相对路径,使用绝对路径
解决2:使用__dirname
表示当前文件所处的目录
fs.readFile(__dirname + '/files/1.txt','utf8',function(err,dataStr){
if(err){
return console.log('读取文件失败!'+ err.message);
}
console.log('读取文件成功',+dataStr)
})
五.path
路径
5.1什么是path路径模块
path模块是Node.js
官方提供的,用来处理路径的模块
例如:
path.join()
方法,用来将多个路径片段拼接成一个完整的路径字符串
path.basename()
方法,用来从路径字符串中,将文件名解析出来
如果要在JavaScript
代码中,使用path
模块来处理路径,则需要使用如下的方式先导入它
const path = require('path')
5.2路径拼接
5.2.1path.join()
的语法格式
path.join([...paths])
参数:
…paths 路径片段的序列
返回值
5.2.2path.join()
的代码示例
// ../ 会抵消前面的路径
const pathStr = path.join('/a','/b/c','../','./d','e')
console.log(pathStr) //输出 \a\b\d\e
const pathStr = path.join(__dirname,'./files/1.txt')
console.log(pathStr) //输出 当前文件所处目录\files\1.txt
5.3获取路径中的文件名
5.3.1path.basename()
的语法格式
使用path.basename()方法,可以获取路径中的最后一部分,经常通过这个方法获取路径中的文件名
path.basename(path[,ext])
参数:
path: 必选参数,表示一个路径的字符串
ext:可选参数,表示移除文件拓展名
返回: 表示路径中的最后一部分
5.3.2path.basename()
的代码示例
const fpath = '/a/b/c/index.html' //文件的存放路径
var fullName = path.basename(fpath)
console.log(fullName) //输出 index.html
var nameWithoutExt = path.basename(fpath,'.html')
console.log(nameWithoutExt) //输出 index
5.4获取路径中的文件扩展名
5.4.1path.extname()
的语法格式
path.extname(path)
参数:
path:必选参数,表示一个路径的字符串
返回:返回得到的扩展名字符串
5.4.2path.extname()
的代码示例
const fpath = '/a/b/c/index.html' //路径字符串
const fext = path.extname(fpath)
console.log(fext) // 输出 .html
六.提取指定内容输出文件案例
描述:
获取
HMTL
文件中的Style
标签中的内容获取
HMTL
文件中的Script
标签的中内容注意:
fs.writeFile()
方法只能用来创建文件,不能用来创建路径- 重复调用
fs.writeFile()
写入同一个文件,新写入的内容会覆盖之前的内容
//1.1 导入fs模块
const fs = require('fs')
//1.2 导入path模块
const path = require('path')
//1.3 定义正则表达式,分别匹配 <style></style> 和 <script></script> 标签
const regStyle = /<style>[\s\S]*<\/style>/
const regScript = /<script>[\s\S]<\/script>/
//2.1 调用 fs.readFile() 方法读取文件
fs.readFile(path.join(__dirname,'../index.html'),'utf8',function(err,dataStr){
//2.2 读取 HTML 文件失败
if(err) return console.log('读取HTML文件失败', err.message);
//2.3 读取文件成功后,调用对应的三个方法,分别拆解出 css,js,html 文件
resolveCSS(dataStr)
resolveJS(dataStr)
resolveHTML(dataStr)
})
//3.1 定义处理 css 样式的方法
function resolveCSS(htmlStr){
//3.2 使用正则提取需要的内容
const r1 = regStyle.exec(htmlStr)
//3.3 将提取出来的样式字符串,进行字符串的replace 替换操作
const newCSS = r1[0].replace('<style>','').replace('</style>','')
//3.4 调用 fs.writeFile() 方法,将提取的样式,写入到clock目录中 index.css 的文件里面
fs.writeFile(path.join(__dirname,'./clock/index.css'),newCSS,function(err){
if(err) return console.log('写入CSS样式失败!'+ err.message)
console.log('写入样式文件成功')
})
}
//4.1 处理 js 脚本
function resolveJS(htmlStr){
//4.2 使用正则提取页面中的 <script></script> 标签
const r2 = regScript.exec(htmlStr)
//4.3 将提取出来的脚本字符串,做进一步的处理
const newJS = r2[0].replace('<script>','').replace('</script>','')
//4.4 将提取出来的js脚本,写入到 index.js 文件中
fs.writeFile(path.join(__dirname,'./clock/index.js'),newJS,err={
if(err) return console.log('写入 JavaScript 脚本失败 !' + err.message)
console.log('写入 JS脚本成功 !')
})
}
//5.1 处理html文件
function resolveHTML(htmlStr){
//5.2 使用字符串的 replace 方法,把内嵌的<style>和<script>标签,替换为外联的 <link> 和 <script> 标签
const newHTML = htmlStr
.replace(regStyle,'<link rel="stylesheet" href="./index.css">')
.replace(regScript,'<script scr="./index.js"></script>')
//5.3 将替换完成之后的html代码,写入到 index.html 文件中
fs.writeFile(path.join(__dirname,'./clock/index.html'),newHTML,err=>{
if(err) return console.log('写入HMTL 文件失败!'+ err.message);
console.log('写入 HMTL 页面成功!')
})
}
七.http
模块
7.1什么http模块
在网络节点中,负责消费资源的电脑,叫做客户端
负责对外提供网络资源的电脑,叫做服务器
http
模块是Node.js
官方提供的,用来创建web服务器的模块可以通过
http.createServer()
方法,就可以把一台普通的电脑,变成一台Web服务器
导入
const http = require('http')
7.2 进一步理解http
模块的作用
服务器和普通电脑的区别在于,服务器上安装了web
服务器软件,例如:IIS
,Apache
等
通过安装这些服务器软件就能把一台普通的电脑变成web
服务器
在Node.js
中,我们不需要使用IIS
,Apache
等这些第三方web
服务器软件
基于Node.js
提供的http
模块,通过几行简单的代码,就能轻松的手写一个服务器软件
7.3服务器相关概念
7.3.1IP
地址
IP地址就是互联网上每台计算机的唯一地址
格式:用"点分十进制" 表示成
(a.b.c.d)
的形式其中,a,b,c,d都是0~255之间的十进制整数
7.3.2域名和域名服务器
IP地址能够标记网络上的计算机,但是不便于记忆
于是发明了域名地址
IP地址和域名是–对应的关系,这份对应关系存放在一种叫做域名服务器(DNS)的电脑中
对应的转换工作由域名服务器实现
域名服务器就是提供IP地址和域名之间的转换服务的服务器
注意:
单纯使用IP地址,互联网中的电脑也能够正常工作,但是又了域名的加持,能让互联网的世界变得更加方便
在开发测试期间,127.0.0.1对应的域名是localhost,它们都代表我们自己的这台电脑,在使用效果上没有任何区别
7.3.3端口号
计算机中的端口号,就好像是现实生活中的门牌号一样
一台电脑中,可以运行成百上千个web服务
每个web服务都对应一个唯一的端口号
客户端发送过来的网络请求,通过端口号,可以被准确地交给对应的web服务进行处理
注意:
- 每个端口号不能同时被多个web服务占用
- 在实际应用中,URL中的80端口可以被省略
7.4创建最基本的web服务器
7.4.1创建web服务器的基本步骤
- 导入http模块
- 创建web服务器实例
- 为服务器实例绑定request事件,监听客户端的请求
- 启动服务器
7.4.1.1导入http模块
const http = require('http')
7.4.1.2创建web服务器实例
const server = http.createServer()
7.4.1.3为服务器实例绑定request事件
//使用服务器实例的 .on()方法,为服务器绑定一个request 事件
server.on('request',(req,res)=>{
//只要有客户端来请求我们自己的服务器,就会触发request事件,从而调用这个事件处理函数
console.log("Someone visit our web server.")
})
7.4.1.4启动服务器
//调用server.listen(端口号,cb回调) 方法,即可启动web 服务器
server.listen(80,()=>{
console.log('http server running at http://127.0.0.1')
})
7.4.2req
请求对象
只要服务器接收到了客户端的请求,就会调用通过server.on()
为服务器绑定的request
事件函数
server.on('request',(req)=>{
//req是请求对象,它包含了与客户端相关的数据和属性
//req.url 是客户端请求的 URL地址
//req.method 是客户端的method 请求类型
})
7.4.3res
响应对象
访问与服务器相关的数据或属性
server.on('request',(req,res)=>{
//res 是响应对象,它包含了与服务器相关的数据和属性
//res.url要发送到客户端的字符串
//res.method使用的方法
//res.end()向客户端发送指定的内容,并结束这场请求的处理过程
})
7.5解决中文乱码问题
当调用res.end()方法,向客户端发送中文内容的时候,会出现乱码问题
需要手动配置内容的编码格式
server.on('request',(req,res)=>{
//发送的内容包含中文
const str = `请求的url地址是${req.url}`
//为了防止中文显示乱码的问题,需要设置响应头 Content-Type 的值为 text/html;charset=utf-8
res.setHeader('Content-Type','text/html;charset=utf-8')
//把包含中文的内容,响应给客户端
res.end(str)
})
八.Node.js
中的模块化
8.1Node.js
中模块的分类
Node.js
中根据模块来源的不同,将模块分为了3大类
- 内置模块(内置模块是由
Node.js
官方提供的,例如fs
,path
,http
) - 自定义模块(用户创建的每个.js文件,都是自定义模块)
- 第三方模块(由第三方开发出来的模块,预先下载)
8.2导入模块
使用require()
方法加载其它模块时,会执行被加载模块中的代码
//加载内置的fs模块
const fs = require('fs')
//加载用户的自定义模块
const custom = require('./custom.js')
//加载第三方模块
const moment = require('moment')
8.3模块作用域
自定义的模块中定义的变量,方法等成员,只能在当前模块内被访问
防止了全局变量污染的问题
九.向外共享模块作用域中的成员
9.1module
对象
在每个.js
自定义模块中都有一个module
对象
存储了当前模块有关的信息
9.2module.exports
对象
在自定义模块中,可以使用module.exports
对象,将模块内的成员共享出去
导入自定义模块时,得到的就是module.exports
所指向的对象
//自定义模块
//默认:module.exports = {}
//向module.exports 对象上挂载 username 属性
module.exports.username = 'zs'
//向module.exports 对象上挂载 sayHello 方法
module.exports.sayHello = function(){
console.log('Hello!')
}
const age = 1;
module.export.age = age;
注意:
使用require()方法导入模块时,导入的结果,永远以module.exports指向的对象为准
module.export = {
nick:"ssssss"
}
//其它被覆盖
9.3CommonJs
模块化规范
- 每个模块内部,
module
变量代表当前模块 module
变量是一个对象,它的exports
属性,是对外的接口- 加载某个模块,其实是加载该模块的
module.exports
属性
十.npm
与包
10.1包
Node.js
中的第三方模块又叫做包
npm install 包的完整名称
npm i 完整的包名称
装包后,多了一个node_modules
的文件夹和package-lock.json
的配置文件
node_modules文件夹
用来存放所有已安装到项目中的包
package-lock.json
配置文件用来记录node_modules
目录下的每一个包的下载信息
安装指定版本的包,通过@符号指定具体的版本,自动替换上一个版本
10.2包的语义化版本规范
包的版本号是以”点分十进制“形式进行定义的
例如:2.24.0
第一位数字:大版本
第二位数字:功能版本
第三位数字:Bug修复版本
只要前面的版本号增长了,则后面的版本号归零
10.3包管理配置文件
包管理配置文件 package.json
快速创建package.json
npm init -y
10.4卸载包
npm uninstall 具体的包名
10.5devDependencies
节点
如果某些包只在项目开发节点会用到,在项目上线之后不会用到
则建议把这些包记录到devDependencies
节点
如果某些包在开发和项目上线之后都需要用到
则建议把这些包记录到dependencies
节点
//安装指定的包,并记录到devDependencies节点中
npm i 包名 -D
//完整写法
npm install 包名 --save-dev
10.6切换npm
的下包镜像源
//查看当前的下包镜像源
npm config get registry
//将下包的镜像源切换位淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/
//检查镜像源是否下载成功
npm config get registry
10.7nrm
//通过npm包管理器,将nrm安装位全局可用的工具
npm i nrm -g
//查看所有可用的镜像源
nrm ls
//将下包的镜像源切换位taobao镜像
nrm use taobao
10.8项目包分类
安装到项目的node_modules目录中的包,都是项目包
分为两类,分别是
- 开发依赖包(开发期间会用)
npm i 包名 -D
- 核心依赖包(开发和上线之后都会用)
npm i 包名
10.9全局包
npm i 包名 -g //全局安装指定的包
npm uninstall 包名 -g //卸载全局安装的包
10.10i5ting_toc
可以把md文档转为html页面的小工具
//将 i5ting_toc 安装为全局包
npm install -g i5ting_toc
//调用 i5ting_toc,实现md转html的功能
i5ting_toc -f 要转换的md文件路径 -o
10.11规范包结构
- 包必须以单独的目录存在
- 顶级目录必须包含
package.json
这个包管理配置文件 package.json
中必须包含name
,version
,main
,分别代表包的名字,版本号,包的入口
十一.开发自己的包
11.1初始化包的基本结构
- 新建包文件夹,作为包的根目录
- 在包文件夹下,新建如下三个文件:
package.json
(包管理配置文件)index.js
(包的入口文件)README.md
(包的说明文档)
11.2package.json
{
"name":'' //名字
"version": //版本号
"main": //入口文件
"description": //描述
"keywords": //搜索关键字
"license": //开源许可协议
}
11.3发布包
- 注册npm账号
- 在终端通过
npm login
命名登录 (下包服务器切换为npm
的官方) - 在包根目录,运行
npm publish
发布包(包不能雷同)
11.4删除包
npm unpublish 包名 --force
十二.模块的加载机制
12.1优先从缓存中加载
模块在第一次加载后会被缓存
多次调用require()
,只会执行一次
12.2内置模块的加载机制
内置模块的加载机制是最高的
12.3自定义模块的加载机制
适用require()
加载自定义模块时,必须指定以./
或../
开头的路径标识符
加载自定义模块时,如果没有指定这样的
node
会把它当作内置模块或第三方模块进行加载
如果省略文件的扩展名
Node.js会按顺序加载以下文件
- 按确切的文件名进行加载
- 补全
.js
扩展名进行加载 - 补全
.json
扩展名进行加载 - 补全
.node
扩展名进行加载 - 加载失败
12.4第三方模块的加载机制
没有写./
或../
开头的路径标识符
尝试从/node_modules文件夹中加载第三方模块
如果没有找到,则移动到再上一层父目录中
12.5目录作为模块
把目录作为模块标识符,传递给require
进行加载的时候
- 在被加载的目录下查找一个叫做
package.json
的文件,并寻找main
属性,作为require()
加载的入口 - 如果目录里没有
package.json
文件,或者main
入口不存在或无法解析,则会加载目录下的index.js
文件 - 如果都失败,报错
总结
个人观看学习视频,产出笔记