数据结构与算法
这一块在笔试、面试的代码题中考核较多,其中常考的数据结构主要有:数组、链表、队列、栈、Set、Map、哈希表等,不同数据结构有不同的方法以及储存原理,这些算是技术岗的必备知识。算法部分主要分为两大块,排序算法与一些其他算法题。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
排序算法根据考频高低主要有:快速排序、归并排序、堆排序、冒泡排序、插入排序、选择排序、希尔排序、桶排序、基数排序、Timsort这十种,这类考核点要么是算法的时间、空间复杂度、稳定度,要么是直接手写代码,故在理解算法原理的同时,对JS语言版的排序算法代码也要加强记忆。
- 二叉树层序遍历
- B 树的特性,B 树和 B+树的区别
- 尾递归
- 如何写一个大数阶乘?递归的方法会出现什么问题?
- 把多维数组变成一维数组的方法
- 知道的排序算法 说一下冒泡快排的原理
- Heap 排序方法的原理?复杂度?
- 几种常见的排序算法,手写
- 数组的去重,尽可能写出多个方法
- 如果有一个大的数组,都是整型,怎么找出最大的前 10 个数
- 知道数据结构里面的常见的数据结构
- 找出数组中第 k 大的数组出现多少次,比如数组【1,2, 4,4,3,5】第二大的数字是 4,出现两次,所以返回 2
- 合并两个有序数组
- 给一个数,去一个已经排好序的数组中寻找这个数的位 置(通过快速查找,二分查找)
mkdir ExpressServer && cd ExpressServer
npm init -y
- 运行如下命令安装
express
:
npm i express
- 创建项目入口文件,并初始化内容如下:
//1. 导入express模块
const express = require(‘express’)
//2. 创建express服务器实例
const server = express()
// TODO:在这里编写服务器代码
//3. 监听服务器80端口
server.listen(80, () => {
console.log(‘Express server running on http://127.0.0.1:80’)
})
- 运行如下命令安装
cors
中间件:
npm i cors
- 在
app.js
中导入并配置cors
中间件:
//1. 导入cors中间件
const cors = require(‘cors’)
//2. 注册cors中间件
server.use(cors())
- 配置如下代码,解析
application/x-www-form-urlencoded
格式的表单数据:
server.use(express.urlencoded({ extended: false }))
-
项目根目录中,创建
router
文件夹,用于存放所有的路由模块 -
项目根目录中,创建
router_handler
文件夹,用于存放所有的路由处理模块
mkdir router
mkdir router_handler
- 在
router
文件夹中新建auth.js
,用于存储所有的用户路由,编写内容如下:
const express = require(‘express’)
//创建路由对象
const router = express.Router()
//用户注册路由
router.post(‘/register’, (req, res) => {
res.send(‘POST /register’)
})
//用户登录路由
router.post(‘/login’, (req, res) => {
res.send(‘POST /login’)
})
//共享router对象
module.exports = router
- 在
app.js
中,导入并注册用户路由模块:
//导入用户路由
const authRouter = require(‘./router/auth’)
//注册用户路由
server.use(‘/api/auth’,authRouter)
- 安装
nodemon
模块,用于启动服务器(nodemon
模块可以在我们修改代码后自动重启服务器):
npm i -g nodemon
- 使用
nodemon
模块启动服务器:
nodemon app.js
如果操作正确,服务器正常启动,将输出如下内容:
PS E:\ExpressServer> nodemon .\app.js
[nodemon] 2.0.16
[nodemon] to restart at any time, enter rs
[nodemon] watching path(s): .
[nodemon] watching extensions: js,mjs,json
[nodemon] starting node .\app.js
Express server running on http://127.0.0.1:80
- 使用
postman
测试接口是否配置正确,以POST
方式分别访问localhost/api/auth/register
和localhost/api/auth/login
为了保证路由模块的存粹性,将路由处理函数单独抽离出来放在
router_handler
文件夹中
- 在
router_handler
文件夹中创建并编辑auth.js
文件如下:
//router_handler/auth.js
//注册处理函数
exports.authRegister = (req, res) => {
res.send(‘POST /register’)
}
//登录处理函数
exports.authLogin = (req, res) => {
res.send(‘POST /login’)
}
- 修改
/router/auth.js
文件代码如下:
//router/auth.js
const express = require(‘express’)
//创建路由对象
const router = express.Router()
//引入auth处理模块
const authHandler = require(‘…/router_handler/auth’)
//用户注册路由
router.post(‘/register’, authHandler.authRegister)
//用户登录路由
router.post(‘/login’, authHandler.authLogin)
//共享router对象
module.exports = router
- 使用
nodemon
启动并使用postman
访问localhost/api/auth/register
和localhost/api/auth/login
,会得到和之前(6.3
)相同的结果。
================================================================
- 创建
MySql
数据库,此处以db_node
为例:
CREATE SCHEMA db_node
;
如果还没有安装MySql,可以在这里下载MySql安装器
- 创建
t_users
数据表,创建表sql
指令如下:
CREATE TABLE db_node
.t_users
(
id
INT NOT NULL AUTO_INCREMENT,
username
VARCHAR(255) NOT NULL,
password
VARCHAR(255) NOT NULL,
nickname
VARCHAR(255) NULL,
email
VARCHAR(255) NULL,
avatar
TEXT NULL,
PRIMARY KEY (id
),
UNIQUE INDEX id_UNIQUE
(id
ASC) VISIBLE,
UNIQUE INDEX username_UNIQUE
(username
ASC) VISIBLE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
- 执行如下指令,安装
mysql
模块:
npm i mysql
- 创建
/db/index.js
文件,此文件用于存储数据库连接对象:
// db/index.js
//导入mysql模块
const mysql = require(‘mysql’)
//创建数据库连接对象
const db = mysql.createPool({
host: ‘127.0.0.1’, //数据库服务器地址,我们使用本机
user: ‘root’, //mysql用户名,替换为你的用户名
password: ‘000000’, //mysql密码,替换为你的密码
database: ‘db_node’,//数据库名称,此处为db_node
})
//导出数据库连接对象
module.exports = db
- 注册步骤
-
检测表单数据
-
检测用户名是否占用
-
密码加密处理
-
插入新用户
- 检测表单数据
const userinfo = req.body
if(!userinfo.username || !userinfo.password){
return res.send({
status: 201,
message:‘用户名、密码不能为空!’
})
}
- 检测用户名是否占用
- 从
db/index.js
导入db
const db = require(‘…/db/index’)
- 定义
SQL
sqlStr = ‘select * from t_users where username = ?’
- 执行
SQL
语句,判断是否占用:
db.query(sql, userinfo.username, (err, results) => {
if (err) return res.send({ status: 201, message: err.message })
if(results.length > 0){
return res.send({status:201,message:‘用户名已存在’})
}
//TODO:插入新用户
})
- 密码加密
- 执行以下指令,安装
bcryptjs
模块
npm i bcryptjs
- 在
router_handler/auth.js
中,导入bcryptjs
const bcrypt = require(‘bcryptjs’)
- 插入用户之前,使用
bcrypt.hashSync(password,len)
进行加密
userinfo.password = bcrypt.hashSync(userinfo.password,10)
- 插入用户
- 定义
SQL
sqlStr = ‘insert into t_users set ?’
- 执行
SQL
,插入用户
db.query(sql, { username: userinfo.username, password: userinfo.password }, (err, results) => {
if (err) return res.send({ status: 201, message: err.message })
if (results.affectedRows === 1)
return res.send({ status: 200, message: ‘success’ })
return res.send({ status: 201, message: ‘注册失败,稍后再试’ })
})
- 使用
PostMan
发送注册信息,操作如下:
- 我们可以查看数据库:
如此,注册方法变成功执行了。
==========================================================================
我们在代码中多次使用到了
res.send()
方法,非常繁琐,需要封装简化代码。(不优化也没啥)
- 在
app.js
中所有的路由之前定义并注册全局中间件
server.use((req, res, next) => {
//status = 200 success
//status = 201 failure
res.cc = function (err, status = 1) {
res.send({
status: status,
message: err instanceof Error ? err.message : err,
})
}
next()
})
这样在所有的路由中,res
都具有一个cc
方法,可以方便的向客户端输出结果。
====================================================================
表单验证,前端为辅,后端为主,永远不相信前端提交的数据
1.安装joi
包,为表单项定义验证规则
npm i joi
- 安装
@escook/express-joi
,实现自动验证表单数据
npm i @escook/express-joi
- 新建
schema/auth.js
用户验证规则模块
mkdir schema
touch schema/auth.js
- 初始化如下:
//schema/auth.js
//导入包
const joi = require(‘joi’)
/**
-
string() 字符串
-
alphanum() 字符数字串
-
min(len) 最短
-
max(len) 最长
-
required() 不为空
-
pattern(reg) 符合正则
*/
//用户名密码验证规则
const username = joi.string().alphanum().min(1).max(10).required()
const password = joi.string().pattern(/1{6,12}$/).required()
//登录注册验证对象
exports.reg_login_schema = {
body: {
username,
password
}
}
- 引入验证中间件
//引入验证中间件
const expressJoi = require(‘@escook/express-joi’) //(*)
- 引入验证规则
//引入验证规则
const { reg_login_schema } = require(‘…/schema/auth’)//(*)
- 注册验证中间件
//用户注册路由,添加验证中间件
router.post(‘/register’, expressJoi(reg_login_schema), authHandler.authRegister) //(*)
修改后的route/auth.js
,如下:
//router/auth.js
const express = require(‘express’)
//创建路由对象
const router = express.Router()
//引入验证中间件
const expressJoi = require(‘@escook/express-joi’) //(*)
//引入验证规则
const { reg_login_schema } = require(‘…/schema/auth’)//(*)
//引入auth处理模块
const authHandler = require(‘…/router_handler/auth’)
//用户注册路由,添加验证中间件
router.post(‘/register’, expressJoi(reg_login_schema), authHandler.authRegister) //(*)
//用户登录路由
router.post(‘/login’, authHandler.authLogin)
//共享router对象
module.exports = router
注意以上代码中(*)
处是修改的地方。
在app.js
中创建并注册全局错误处理中间件,用于处理验证错误(也可以处理其他错误)。
- 引入验证规则
//引入验证规则模块
const joi = require(‘joi’)
- 创建并注册全局异常中间件
//引入验证规则模块
const joi = require(‘joi’)
//注册异常捕获中间件
server.use((err, req, res, next) => {
if (err instanceof joi.ValidationError) return res.cc(err)
res.cc(err)
})
================================================================
-
表单验证;
-
数据查询;
-
密码比较;
-
生成
JWT
的Token
字符串
- 修改
router/auth.js
的路由如下:
//用户登录路由
router.post(‘/login’, expressJoi(reg_login_schema), authHandler.authLogin)
在router_handler/auth.js
中的登录处理方法中:
- 表单数据接收
const userinfo = req.body
- 定义
SQL
语句
const sqlStr = ‘select * from t_users where username=?’
- 执行查询
SQL
//执行查询
db.query(sqlStr, userinfo.username, (err, results) => {
//查询失败
if (err) return res.cc(err)
//查询结果不合理
if (results.length !== 1) return res.cc(“登录失败”)
//TODO:判断密码
})
调用
bcrypt.compreSync(表单密码,数据库密码)
判断密码是否一致,true
一致,false
不一致
//判断密码
ajax
1)ajax请求的原理/ 手写一个ajax请求?
2)readyState?
3)ajax异步与同步的区别?
4)ajax传递中文用什么方法?
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
- 生成
JWT
的Token
字符串
- 修改
router/auth.js
的路由如下:
//用户登录路由
router.post(‘/login’, expressJoi(reg_login_schema), authHandler.authLogin)
在router_handler/auth.js
中的登录处理方法中:
- 表单数据接收
const userinfo = req.body
- 定义
SQL
语句
const sqlStr = ‘select * from t_users where username=?’
- 执行查询
SQL
//执行查询
db.query(sqlStr, userinfo.username, (err, results) => {
//查询失败
if (err) return res.cc(err)
//查询结果不合理
if (results.length !== 1) return res.cc(“登录失败”)
//TODO:判断密码
})
调用
bcrypt.compreSync(表单密码,数据库密码)
判断密码是否一致,true
一致,false
不一致
//判断密码
ajax
1)ajax请求的原理/ 手写一个ajax请求?
2)readyState?
3)ajax异步与同步的区别?
4)ajax传递中文用什么方法?
[外链图片转存中…(img-NLChKsJX-1715628267917)]
[外链图片转存中…(img-1ZwBojs4-1715628267918)]
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
\S ↩︎