ES6
ECMA ECMAScript6 JS的第6套标准规范
ES2015 ES2016---ES2021
(1)块级作用域
let声明的变量不存在提升,不允许重复声明同一个变量
大括号之间的语句块就是块级作用域,例如:if、else、while、for。。。
块级作用域下,let和const声明的都属于局部的,外部无法访问
对比var、let、const 三者的区别
var 声明的变量存在提升,允许重复声明同一个变量
let 声明的变量不存在提升,不允许重复声明同一个变量,存在块级作用域
const 声明的常量必须赋值,不允许重新赋值,存在块级作用域
let 和 const 声明的在全局作用域下,也不是全局变量
(2)参数增强
可以给函数中参数设置默认值
function fn(a, b){ //如果实参不存在,会使用默认值0 b = b || 0; //ES6之前的写法 } fn(8000,5000); fn(8000);
(3)箭头函数
简化了匿名函数的写法,不等价于匿名函数
// ()=>{}
sort( (a,b) ) => {
return a-b;
}
如果箭头函数的函数体中只有一行代码,并且是return形式,可以进一步简化成功 sort((a, b) => a-b )
(4)模板字符串
`反引号之间的内容就是模板字符${JS表达式}`
Node.js
1.Node.js
概述运行在服务器的JS环境
(1)对比JS
JS运行在客户端浏览器,存在多款浏览器,有兼容性问题,Node.js运行在服务器端,只有一种解析器,没有兼容性问题
两者都有相同的内容之对象、自定义对象,不同的宿主对象
JS用于开发网页中的交互效果,Node.js用户服务器端的开发,例如:数据库访问,其他服务器调用
(2)运行
脚本模式
node 拖拽文件
交互模式
node 回车———进入交互模式
两次 ctrl + c 或者 一次 ctrl + d —— 退出
(3)特点
是单线程运行,支持数万个并发连接,适合做基于社交网络的大规模WEB应用
(4)API文档
www.nodejs.cn 中文网
www.nodejs.org 英文官网
2.全局对象
(1)global
检测一个变量或者函数是否为全局的
在Node.js下,一个JS文件不是全局作用域,防止全局污染
在JS下,一个JS文件是在全局作用域,存在全局污染
JS下的global 对象名称 window
(2)console
控制台对象,用于输出到控制台
console.log(1); //日志 console.info(2); //消息 console.warn(3); //警告 console.error(4); //错误 console.time(); //开始计时 console.timeEnd(); //结束计时
开始计时和结束计时的参数要保持一致
练习:统计while,do-while,for循环100000次的耗时
//开始计时 console.time('tao'); for(var i=1;i<=100000;i++){ } //结束计时 console.timeEnd('tao'); console.time('while'); var j=1; while(j<=100000){ j++; } console.timeEnd('while'); console.time('do-while'); var k=1; do{ k++; }while(k<=100000); console.timeEnd('do-while');
(3)process
进程:计算机上启动的每一个软件都是一个进程,每个进程都有相应的CPU,内存占用
//process 是Node.js进程对象 process.arch(); //查看CPU的架构 process.platform(); //查看操作系统 process.pid(); //查看当前的进程编号 process.kill(); //结束指定编号的进程
(4)Buffer
缓冲区:是内存中的区域,用于临时存储数据
var buf = Buffer.alloc(5, 'abcde'); //创建buffer,分配空间大小,并存储数据,单位是字节,1个汉字占3个字节 buf.toString(); //将Buffer数据转为字符串格式
模块
每个模块是一个功能体,每个文件就是一个模块,一个模块可以被其他的模块所引入
1.模块中的成员
require(); //用于引入其他的模块 modeule.exports = ?; //当前模块导出的对象(暴露的内容),默认是一个空对象 __dirname; //获取当前模块的绝对路径 __filename; //获取绝对路径+模块名称
2.模块的分类
分为自定义模块、核心模块、第三方模块
3.包和npm
包:就是指第三方模块
npm:用来管理包的工具,例如:下载、上传、更新、卸载。。。
npm在Node.js安装的时候会附带安装
num -v 查看npm版本
CommonJS:是Node.js的模块规范,引入,暴露都是基于这个规范
网址: www.npmjs.com
(1)切换命令行的路径

(2)npm命令
npm init -y; //会在命令行对应的目录下创建package.json ,作为项目说明文件,可以记录下载的包都有哪些 npm install 包名称; //下载安装指定的包,将包放入到 node_modules 目录,如果目录不存在会自动创建;同时会生成记录所有包的版本号;在package.json 中也会记录下载的包 npm install; //会自动读取package.json 和 package-lock.json中记录的包并安装 //其他npm命令,参考: www.npmjs.cn
4.查询字符串模块(querystring)
如: price=5000&sex=男
查询字符串:是浏览器向服务器传递参数的一种方式,位于网址中
查询字符串模块:用于操作查询字符串的工具
parse()
将查询字符中的参数转为对象
练习:获取以下查询字符串中传递的参数
ename=tao&sex=1&salary=50000
最后打印格式 ‘姓名:xxx 性别:x 工资:xxx ’
const querystring=require('querystring');
var str='ename=tao&sex=0&salary=50000';
var obj=querystring.parse(str);
console.log(obj);
console.log(`
姓名:${obj.ename}
性别:${parseInt(obj.sex) ? '男' : '女'}
工资:${obj.salary}
`);
5.网址模块(url)
URL:统一资源定位,互联网上任何的资源都有对应URL,URL用来访问资源
资源(html,css,js,图像,声音...)
http://www.codeboy.com:9999/product_details.html?lid=1#one 协议 域名/IP地址 端口 文件在服务器的路径 查询字符串 锚点 new URL() 将一个URL转换为对象,可以获取其中各个部分
练习:获取以下URL中传递的数据
https://www.tmooc.cn:443/course/web.html?cid=2109&cname=nodejs#two
最后打印 ‘课程编号:xxx 课程名称:xxx’
//引入查询字符串模块 const querystring=require('querystring'); var str='https://www.tmooc.cn:443/course/web.html?cid=2109&cname=nodejs#two'; //转换为对象 var obj=new URL(str); //获取查询字符串部分 var str2=obj.search.slice(1); //console.log(str2); //将查询字符串转为对象 var obj2=querystring.parse(str2); console.log(obj2); console.log(`课程编号:${obj2.cid} 课程名称:${obj2.cname}`);
6.定时器
(1)一次性定时器
//开启 var timer = setTimeout(回调函数,间隔时间); //当间隔时间到了,会调用一次回调函数 //清除 clearTimeout(timer);
(2)周期性定时器
//开启 var timer = setInterval(回调函数,间隔时间); //,每隔一段时间,调用一次回调函数 //清除 clearInterval(timer);
(3)立即执行定时器
setImmediate(回调函数)/clearImmediate() process.nextTick(回调函数) //没有清除

练习:使用周期性定时器每隔3秒钟打印'hello',打印3次后清除定时器。
预习nodejs第3天
//练习:使用周期性定时器每隔3秒钟打印'hello',打印3次后清除定时器。 //声明变量用于计数 var num=0; var timer=setInterval(()=>{ console.log('hello'); //打印一次,记录一次 num++; //判断是否为3 if(num===3){ clearInterval(timer); } },1000);
同步和异步
1.同步和异步
同步:在主线程中执行,会阻止后续代码的执行,通过返回值获取结果
异步:在一个独立的线程执行,不会阻止主程序中后续代码的执行,结果以回调函数的形式获取
2.文件系统模块(fs)
文件分为文件形式和目录形式
//左边同步,右边异步
(1)查看文件的状态
statSync(文件的路径) / stat(文件的路径,回调函数) isFile(); //是否为文件形式 isDirectory(); //是否为目录形式
(2)创建目录
mkdirSync(目录的路径); / mkdir(目录的路径,回调函数);
(3)移除目录
rmdirSync(目录的路径); / rmdir(目录的路径,回调函数);
(4)读取目录
readdirSync(目录的路径); / readdir(目录的路径,回调函数); //读取的结果为数组格式
(5)清空写入文件
writeFileSync(文件的路径,写入的数据); / writeFile(文件的路径,写入的数据,回调函数); //如果文件不存在,先创建文件然后写入数据
(6)追加写入文件
appendFileSync(文件的路径,写入的数据); / appendFile(文件的路径,写入的数据,回调函数); //如果文件已经存在,会在文件的末尾追加写入数据
(7)读取文件
readFileSync(文件的路径); / readFile(文件的路径,回调函数); //读取的数据格式为buffer
(8)删除文件
unlinkSync(文件的路径); / unlink(文件的路径,回调函数);
(9)检测文件是否存在
existsSync(文件的路径); //存在 -> true ; 不存在 -> false
(10)拷贝文件
copyFileSync(原文件路径,目标文件路径); / copyFile(源文件路径,目标文件路径,回调函数);
2.文件流
createReadStream(); //创建可读取的流对象,分段读取一个文件 createWriteStream(); //创建可写入的流,文件不存在会自动创建 pipe(); //管道,可以将读取的流分段添加到写入的流 on(事件名称,回调函数); //添加事件,事件名称是固定的字符串,一旦触发事件自动执行回调函数 //获取流入到内存的每一段数据 //添加事件:监听是否有数据流入,一旦有数据流入通过回调函数获取这段数据 //'data':固定用法,表示数据流入事件 var count=0; rs.on('data',(chunk)=>{ //chunk获取的分段数据 //console.log(chunk); count++; }); //添加事件:监听是否读取结束,一旦结束执行回调函数 rs.on('end',()=>{ console.log(count); });
3.http协议
超文本传输协议:是浏览器和WEB服务器之间的通信协议
(1)通用头信息
Request URL: 请求的URL,要请求的服务器上的资源 Request Method: 请求的方法,对资源的操作方法 get/post Status Code: 响应的状态码 1**: 接收到了部分请求,还没有做出响应 2**: 成功的响应 3**: 响应的重定向 4**: 客户端请求错误 5**: 服务器错误
(2)响应头信息(Response)
Location: 设置要跳转的URl,结合状态码 3** 使用
Content-Type: 设置响应的内容类型,解决中文乱码 text/html;charset=utf-8
(3)请求头信息(Request)
(4)请求主体
只有在传递数据的时候才会出现
http模块
可以用来创建WEB服务器
http.creadteServer(); //创建WEB服务器 listen(); //设置端口,用来请求WEB服务器 //通过事件接受请求,做出响应 app.on('request',(req,res)=>{ //req 请求对象 //res 响应对象 res.writeHead(状态码,头信息); //设置响应的状态码和头信息 res.write(); //设置显示到浏览器的内容 res.end(); //结束并发送到浏览器 }); //设置端口 app.listen(8080,()=>{ console.log('服务器启动成功'); }); //请求服务器 // http://127.0.0.1:8080 // http://localhost:8080 //如: //接收请求,作出响应 //给服务器添加事件,一旦请求,自动执行回调函数 app.on('request',(req,res)=>{ //req 请求的对象 //res 响应的对象 //设置头信息中内容类型 res.writeHead(200,{ 'Content-Type':'text/html;charset=utf-8' }); //设置响应到浏览器的内容 res.write('这是你的jianbing'); //结束并发送 res.end(); });
练习:创建WEB服务器,设置端口,添加事件接收请求,响应1.html网页到浏览器端(先使用同步方法读取文件数据,然后设置设响应的内容)
//引入http模块 const http=require('http'); //引入fs模块 const fs=require('fs'); //创建WEB服务器 const app=http.createServer(); //设置端口,用来请求WEB服务器 app.listen(8080,()=>{ console.log('服务器启动成功'); }); //添加事件,接收请求并作出响应 app.on('request',(req,res)=>{ //req请求的对象 //获取请求的URL,请求的方法 console.log(req.url,req.method); //设置响应的状态码和内容类型 res.writeHead(200,{'Content-Type':'text/html;charset=utf-8' }); //读取1.html文件中的数据 var data=fs.readFileSync('./1.html'); //把读取的文件作为要响应的内容 res.write(data); //结束并发送响应 res.end(); //设置状态码为302,跳转的URL res.writeHead(302,{Location:'https://www.tmooc.cn/'}); //结束并发送 res.end(); //设置状态码为404 res.writeHead(404); //设置响应浏览器内容为 'not found' res.write('not found'); //结束并发送 res.end(); });
web 服务器下的响应对象(req)
req.url 获取请求的URL(资源名称)
req.method 获取请求的方法,默认是get
express框架
框架:是一整套解决方案,简化了已有的功能,添加了新的功能,专门用于项目开发。
1.express框架
基于Node.js平台,快速、开放、极简的WEB开发框架
属于第三方模块,需要自行下载
在 cmd 中 npm install express
(1)路由
路由用来处理特定的请求,包含三部分:请求的方法、请求的URL、回调函数、res响应对象
res 响应对象
res.send() 设置相应的内容并发送
res.redirect() 设置响应的重定向
res.sendFile() 设置响应的文件,需要使用绝对路径 __dirname
req 请求的对象
req.url 获取请求的URL
req.method 获取请求的方法
req.query 获取请求的URL中查询字符串传的参数,格式为对象
get传参:
网址?kw=dell req.query 格式为对象 {kw:'dell'}
路由传参:
网址/keyword 需要加入形参 /:pname req.params 格式为对象 {pname:'keyword'}
post传参:
URL中不可见 以流的方式,通过事件获取
req.body 获取对象的参数
//引入express模块 const express=require('express'); //创建WEB服务器 const app=express(); //设置端口 app.listen(8080); //添加路由(get /search) app.get('/search',(req,res)=>{ //响应文件 res.sendFile(__dirname+'/search.html'); }); //添加路由(get /mysearch),处理表单的提交,响应'搜索成功' app.get('/mysearch',(req,res)=>{ //获取请求的URL,获取请求的方法 //console.log(req.url, req.method); //将URL中查询字符串转为对象 console.log(req.query); res.send('搜索成功'); }); //路由(get /login),响应文件 app.get('/login',(req,res)=>{ res.sendFile(__dirname+'/login.html'); }); //路由(get /mylogin) app.get('/mylogin',(req,res)=>{ //获取get传递的参数 console.log(req.query); res.send('登录成功'); }); //练习:添加路由用于查看包的详情介绍(get /package),响应'这是包的使用介绍' //路由传参 app.get('/package/:pname',(req,res)=>{ //获取路由传参的值 console.log(req.params); res.send('这是包的使用介绍'); });
2.路由器
用来管理路由,将同一个模块下所有的路由放入到一个路由器,最后在WEB服务器下使用路由器
//路由器模块,创建路由器对象 const r = express.Router(); //2.添加路由 //3.暴露路由器对象 module.exports = r; //之后在WEB服务器中 app.use(要添加的前缀引入的路由器名称);

3.中间件
中间件用于拦截对服务器的请求
中间件分为应用级中间件、路由中间件、内置中间件、第三方中间件、错误处理中间件
(1)应用级中间件
就是一个函数,一旦拦截到自动调用这个函数
function fn(req,res){ next() //往后继续执行下一个中间件或者路由 } app.use(拦截的URL,fn);
(2)路由中间件
路由器的使用
app.use('/user',路由器);
一旦拦截到,会到路由器下查找路由
(3)内置中间件
静态资源:html\css\js\图像\视频....
托管静态资源:客户端要请求静态资源,不需要通过路由去响应文件,而是自动到指定的目录查找
app.use(express.static('目录的路径'))
(4)第三方中间件
将post传递的参数转为对象
app.use(express.urlencoded({ extened:false //内部使用querystring })); //在路由中获取对象 req.body;
mysql模块
复习MySql基础用法
mysql -uroot<拖拽脚本文件 mysql.exe -h127.0.0.1 -P3306 -uroot -p insert into 表名称 values(...); update 表名称 set 列=值,列=值 where 条件; delete from 表名称 where 条件;
1.mysql模块
是Node.js 下专门用于操作MySql数据库的模块
属于第三方模块,需先下载 npm install mysql;
createConnection() 创建普通连接
createPool() 创建连接池,产生多个连接,执行SQL命令的时候会从连接池中获取连接,执行完再把连接归还到连接池
query(SQL 命令,回调函数) 执行SQL命令,加入新的SQL命令。
SQL注入:是对数据库的攻击方式,破坏原来的SQL命令,加入新的SQL命令。
解决方法:对用户传递的值进行过滤
mysql模块使用占位符(?) 对传递的值进行过滤
2.接口
后端为前端提供的动态资源
RESTful接口:是一种接口的规范
(1)URL
http://127.0.0.1:8080/v1/emps
版本号 资源名称
http://127.0.0.1:8080/v1/emps/2
单个资源
http://127.0.0.1:8080/v1/users/login
特殊操作
(2)请求方法
对资源的操作方式
get 获取资源
detele 删除资源
put 修改资源
post 新建资源
(3)过滤数据
使用get传参
http://127.0.0.1:8080/v1/emps?pno=1&count=9
分页过滤 页码 每页数量
http://127.0.0.1:8080/v1/emps?s1=4000&s2=7000
工资过滤 工资开始 工资结束
(4)返回结果
格式json
包含状态码、消息、数据
登录的成功结果
{"code":200,"msg":"登录成功"}
获取一组员工结果
{"code":200,"msg":"获取成功","data":[....]}
3.ApiPost
接口测试工具,可以生成接口使用文档

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
多个send被调用,说明响应多次,只能响应一次
test() 检测是否符合规则
repalce() 用于查找并替换
较完整的前后台数据传参的代码:
//引入express const express=require('express'); //引入mysql模块 const mysql=require('mysql'); //创建连接池对象 const pool=mysql.createPool({ host:'127.0.0.1', port:'3306', user:'root', password:'', database:'tedu', connectionLimit:15 }); //创建WEB服务器 const app=express(); //设置端口 app.listen(8080); //使用中间件将post传递参数转为对象 app.use( express.urlencoded({ extended:false }) ); //添加员工路由(post /v1/emps) //接口地址:http://127.0.0.1:8080/v1/emps //请求方法:post app.post('/v1/emps',(req,res)=>{ //获取post传递的参数 console.log(req.body); //执行SQL命令,将数据插入到数据表emp pool.query('insert into emp set?',[req.body],(err,result)=>{ if(err) throw err; console.log(result); //获取了成功的结果,再去响应 res.send({code:200,msg:'员工添加成功'}); }); }); //按照编号查找员工(get /v1/emps/编号) //接口地址:http://127.0.0.1:8080/v1/emps/2 //请求方法:get app.get('/v1/emps/:eid',(req,res)=>{ //获取路由传参的值 console.log(req.params); //执行SQL命令,查询编号对应的员工 pool.query('select * from emp where eid=?',[req.params.eid], (err,result)=>{ if(err) throw err; console.log(result); //查询的结果是数组,如果是空数组说明员工不存在,否则说明存在 if(result.length===0){ res.send({code:201,msg:'查无此人'}); }else{ res.send({code:200,msg:'查询成功',data:result}); } }); }); //删除员工(delete /v1/emps/编号) //接口地址:http://127.0.0.1:8080/v1/emps/2 //请求方法:delete app.delete('/v1/emps/:eid',(req,res)=>{ //获取路由传参的值 console.log(req.params); //执行SQL命令 pool.query('delete from emp where eid=?',[req.params.eid],(err,result)=>{ if(err) throw err; console.log(result); //结果是对象,如果对象下的affectedRows的值是0说明删除失败,否则删除成功 if(result.affectedRows===0){ res.send({code:201,msg:'删除失败'}); }else{ res.send({code:200,msg:'删除成功'}); } }); });
浙公网安备 33010602011771号