2025最新面试自用题库---面试使用
- 1、css中如何实现水平垂直居中
- 方法一:flex:
- 方法二:绝对定位+margin:auto:
- 方法三:已知子元素宽高(200*200) + 绝对定位 + 负margin
- 方法四:已知子元素宽高(200*200) + 绝对定位 + calc
- 方法五:绝对定位 + transform
- 方法六:table-cell实现
- 方法七:Grid
- 2、数组相关API有哪些
- 3、数组去重
- 例:将下面数组去除重复元素(以多种数据类型为例)
- 方法一:利用Set()+Array.from()
- 方法二:新数组 + forEach + indexof / includes
- 方法三:两层循环 + splice
- 方法四:filter() + indexOf()
- 方法五:map() + has() + set()
- 方法六:利用对象
- 4、Promise相关方法以及对Promise的一些了解
- 5、如果Promise只要一个成功就成功的方法
- 6、Vue3对Vue2的优化
- 7、Vue源码碰过吗?关于响应式的原理知道吗
- 8、vue 3 的响应式是如何实现的?
- 8、事件循环
- 9、npm install之后发生了什么?
- 10、npm常用命令
- 11、理解CI/CD(持续集成/持续部署)技术的意义,至少熟练掌握一种CI/CD工具的使用
- a、 持续集成与持续部署的区别是什么?
- b、为什么CI/CD对企业如此重要?它的作用价值?
- 12、说一下 v-if 和 v-show 的区别,以及它们的使用场景。
- 踩坑
- 2025最新面试题(真实反馈)
1、css中如何实现水平垂直居中
方法一:flex:
display: flex;
justify-content: center;
align-item: center;
方法二:绝对定位+margin:auto:
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin:auto;
方法三:已知子元素宽高(200*200) + 绝对定位 + 负margin
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
方法四:已知子元素宽高(200*200) + 绝对定位 + calc
position: absolute;
top: calc(50% - 100px);
left: calc(50% - 100px);
方法五:绝对定位 + transform
position: absolute;
left: 50%; (定位父元素的50%)
top: 50%;
transform: translate(-50%, -50%); (自己的50%)
方法六:table-cell实现
display: table-cell;
text-align: center;
vertical-align: center;
方法七:Grid
display: grid;
justify-self: center;
align-self: center;
2、数组相关API有哪些
- 尾巴新增/删除元素:
push()
、pop()
、 - 正序/倒序:
sort()
、reverse()
- 前面删除/新增元素:
shift()
、unshift()
- 数组截取 - 返回数组的指定部分,创建一个新的数组:
slice()
- 数组修改 - 通过删除、替换或添加元素的方式修改数组,并返回被删除的元素:
splice()
- 数组拼接 / 数组指定的分隔符拼接转为字符串 / 求和 :
concat()
、join()
、reduce()
- 遍历:
forEach()
、map()
- 数组筛查 / 数组填充 :
filter()
、fill()
- 数组过滤 / 判断数组中是否包含:
find()
、include()
- 数组查找定位:
indexOf()
、findIndex()
、lastIndexOf()
- 转字符串:
toString()
、toLocaleString()
3、数组去重
例:将下面数组去除重复元素(以多种数据类型为例)
const arr = [1, 2, 2, 'abc', 'abc', true, true, false, false, undefined, undefined, NaN, NaN]
方法一:利用Set()+Array.from()
const result = Array.from(new Set(arr))
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]
方法二:新数组 + forEach + indexof / includes
indexof
无法检测NaN
includes
支持全类型:因为includes 在进行判断是否包含某元素时会调用sameValueZero
方法进行比较,如果为NaN
,则会使用isNaN()
进行转化
function removeDuplicate(arr) {const newArr = []arr.forEach(item => {if (newArr.indexOf(item) === -1) {// if (!newArr.includes(item)) {newArr.push(item)}})return newArr // 返回一个新数组
}const result = removeDuplicate(arr)
console.log(result)
// 使用indexOf:[ 1, 2, 'abc', true, false, undefined, NaN, NaN ]
// 使用includes:// [ 1, 2, 'abc', true, false, undefined, NaN ]
方法三:两层循环 + splice
- 通过两层循环对数组元素进行逐一比较,然后通过splice方法来删除重复的元素。
- 无法检测
NaN
:此方法对NaN是无法进行去重的,因为进行比较时NaN !== NaN。
function removeDuplicate(arr) {let len = arr.lengthfor (let i = 0; i < len; i++) {for (let j = i + 1; j < len; j++) {if (arr[i] === arr[j]) {arr.splice(j, 1)len-- // 减少循环次数提高性能j-- // 保证j的值自加后不变}}}return arr
}const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]
方法四:filter() + indexOf()
- filter方法会对满足条件的元素存放到一个新数组中,结合indexOf方法进行判断。
- 无法检测
NaN
function removeDuplicate(arr) {return arr.filter((item, index) => {return arr.indexOf(item) === index})
}const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined ]
注意:这里的输出结果中不包含NaN,是因为indexOf()无法对NaN进行判断,即arr.indexOf(item) === index返回结果为false。
方法五:map() + has() + set()
Map对象是JavaScript提供的一种数据结构,结构为键值对形式,将数组元素作为map的键存入,然后结合has()和set()方法判断键是否重复。
function removeDuplicate(arr) {const map = new Map()const newArr = []arr.forEach(item => {if (!map.has(item)) { // has()用于判断map是否包为item的属性值map.set(item, true) // 使用set()将item设置到map中,并设置其属性值为truenewArr.push(item)}})return newArr
}const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]
注意:使用Map()也可对NaN去重,原因是Map进行判断时认为NaN是与NaN相等的,剩下所有其它的值是根据 === 运算符的结果判断是否相等。
方法六:利用对象
利用了对象的属性名不可重复这一特性
function removeDuplicate(arr) {const newArr = []const obj = {}arr.forEach(item => {if (!obj[item]) {newArr.push(item)obj[item] = true}})return newArr
}const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]
4、Promise相关方法以及对Promise的一些了解
- 异步、代理、设计模式
- 基于 Promise 可以有效管理JS中的异步编程
- 解决传统异步编程 + 回调函数导致的“回调地狱”问题
- 状态:初始状态(
pending
)、兑现成功(fulfilled、resolved
)、操作失败(rejected
) - 常用API:
Promise.all()
、Promise.any()
、Promise.race()
、Promise.resolve()
、Promise.reject()
、Promise.prototype.then()
、Promise.prototype.fecth()
、Promise.prototype.finally()
5、如果Promise只要一个成功就成功的方法
Promise.any()
6、Vue3对Vue2的优化
7、Vue源码碰过吗?关于响应式的原理知道吗
8、vue 3 的响应式是如何实现的?
- 总:
vue3
的响应式实现主要有两个部分:reactive
、ref
。 - 分:
reactive
主要是通过proxy
进行的响应式实现,核心是监听复杂数据类型的getter
和setter
行为。当监听到 getter 行为的时候那么就收集当前的依赖行为,也就是effect
。 当触发 setter 行为的时候,那么就触发刚才收集的依赖。那么此时,所有获取到当前数据的地方都会更新执行,也就是完成了响应性。
但是 proxy 只能监听复杂数据类型,没有办法监听简单数据类型。所以 vue 专门提供了ref
方法。 ref 方法既可以处理简单数据类型、也可以处理复杂数据类型。 它的实现在 3.2 之前和 3.2 之后是不同的。
- 3,2 之前主要通过
Object.defineProperty
进行实现,- 在 3.2 版本的时候,根据社区贡献改为了
get value
和set value
标记的方式进行实现。这也是为什么
ref
类型的数据必须要通过.value
的方式使用的原因(本质上是触发 value 方法)。
当ref
接收复杂数据类型的时候,会直接通过toReactive
方法,把复杂数据类型交给reactive
进行处理。
- 总:
整个的 vue3 响应性,主要就是由这两大块来进行实现的。proxy
处理复杂数据类型,get value
和set value
处理简单数据类型。核心都是监听 setter 和 getter ,然后触发 effect 的方式
8、事件循环
9、npm install之后发生了什么?
- 首先,
npm install
需要检查是否有附加的命令参数,如-g
、--save
、--saved-dev
,以决定依赖类型(全局、生产依赖、开发依赖)。如果没有指定,则之后会安装package.json
中列出的所有依赖。- 接着,
npm install
会按优先级查找配置文件
: 项目级.npmrc > 用户级 .npmrc > 全局级 .npmrc > npm 内置 .npmrc,并根据配置调整安装行为。- 如果项目定义了
preinstall
钩子(例如:npm run preinstall
),它会在依赖安装前被执行。可以在此步骤进行一些初始化操作,如检查版本、清理缓存等。- 然后检查是否有
lock
文件,有的话会检查package.json
中的依赖版本是否和package-lock.json
中的依赖有冲突。如果没有冲突,直接在缓存中查找包信息。
如果没有lock文件,会先从npm远程仓库
去获取包信息,之后根据package.json构建依赖树,具体过程:
a、构建依赖树
时,不管其是直接依赖还是子依赖的依赖,优先将其放置在 node_modules根
目录。
b、当遇到相同模块时,判断已放置在依赖树的模块版本是否符合新模块的版本范围,如果符合则跳过,不符合则在当前
模块的 node_modules 下放置该模块。- 之后再在
缓存
中依次查找依赖树的每个包:
a、不存在缓存:从npm远程仓库下载包,检验包的完整性,检验不通过就重新下载,检验通过会将下载的包复制到npm缓存目录并按照扁平化
的依赖结构解压到node-modules中
b、存在依赖:将缓存按照扁平化的依赖结构解压到node-modules
中- 生成
lock
文件
10、npm常用命令
npm install moduleName # 安装模块到项目目录
npm install -g moduleName # -g 意思是将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix 的位置。
npm install --save moduleName # --save 的意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖。
npm install --save-dev moduleName # --save-dev 的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖。
11、理解CI/CD(持续集成/持续部署)技术的意义,至少熟练掌握一种CI/CD工具的使用
a、 持续集成与持续部署的区别是什么?
CI
:持续集成,代码合并提交,主要关注开发阶段,确保每次代码提交后都能通过自动化构建和测试,从而尽早发现并修复问题
CD
:持续部署,不仅将代码集成到主分支,还会自动将经过测试的代码直接部署到生产环境,实现快速迭代和反馈
b、为什么CI/CD对企业如此重要?它的作用价值?
提升代码质量
:每次代码提交后都会触发自动化测试,及时发现并修复问题,降低代码缺陷率加速产品交付速度
:实现了每日多次部署,极大地提升了用户体验和客户满意度。促进团队协作
:减少了沟通成本,提高了工作效率增强风险控制能力
:通过自动化测试和监控,确保每一个版本都是安全可靠的,故障恢复时间大幅缩短。
12、说一下 v-if 和 v-show 的区别,以及它们的使用场景。
- 总:
v-if
和v-show
都是用来控制元素是否展示的。但是它们的实现原理和在项目中的应用场景确实有一定区别。 - 分:
那么咱们先说实现原理。
v-show
主要通过css
属性diplay:none;
来控制元素的显示和隐藏。那么虽然用户看不到,但是dom
依然是存在的。- 而
v-if
主要通过是否渲染
来控制元素的展示和消失。当用户看不到它的时候,那么这个元素是不存在的。这样一个存在和不存在的特性,如果是在企业项目中差别就会比较大了。特别是在组件上使用时,其中会涉及到 生命周期 以及 状态保存 的问题。
比如,通过一个
dialog
来处理编辑用户功能。
- 那么使用
v-show
时。当页面展示时,dialog 就已经被渲染出来了。那么这就意味着 dialog 的生命周期已经完成,如果涉及到props
传参,那么其实参数就已经传递了。同时当修改了 dialog 的数据,关闭 dialog 时,那么 dialog 的状态会被保持。- 而使用
v-if
的话。当页面展示时,dialog 是没有被渲染的。只有主动触发绑定值变化,dialog 才会显示出来。这就意味着,此时 dialog 的生命周期会执行,同时props
才开始传递。同时当修改了 dialog 的数据,关闭 dialog 时,那么 dialog 的状态会被清空(组件消失)。v-show 的性能相对会更高,而 v-if 会更加消耗性能。
但是很多场景中,性能的消耗对于用户而言,感知是有限的。
- 总:
所以,v-if 和 v-show 的选择,我们需要基于当前 dialog 的业务场景来进行判断。
- 如果当前 dialog
需要保存状态
或者需要进行初始渲染
,那么可以使用v-show
。- 如果当前 dialog
不需要保存状态
或者希望控制它的渲染时机
,那么可以使用 v-if。
[代码实现]JS 中如何实现大对象深度对比
如何理解数据驱动视图,有哪些核心要素?
vue-cli都做了哪些事儿,有哪些功能?
JS 执行100万个任务,如何保证浏览器不卡顿?
JS 放在 head 里和放在 body 里有什么区别?
Eslint 代码检查的过程是啥?
虚拟混动加载原理是什么,用JS代码简单实现一个虚拟 滚动加加载
[React]react-router和 原生路由区别
html的行内元素和块级元素的区别
介绍-下requestldleCallbackapi
documentFragmentapi是什么,有哪些使用场景?
git pull和 git fetch 有啥区别?
前端如何做 页面主题色切换
前端视角-如何保证系统稳定性
如何统计长任务时间、长任务执行次数
web 应用中如何对静态资源加载失败的场最做降级处理
html中前缀为 data-开头的元素属性是什么?
移动端如何实现上拉加载,下拉刷新?
如何判断dom元素是否在可视区域
前端如何用 canvas 来做电影院选票功能
如何通过设置失效时间清除本地存储的数据?
如果不使用脚手架,如果用webpack构建个自己的 react应用
用 nodejs实现一个命令行工具,统计输入目录下面指定文件 代码的行数
package.json 里面 sideEffects 属性的作用是
script标签上有那些属性,分别作用是啥?
为什么 SPA应用都会提供一个 hash 路由,好处是什么?
[React]如何进行路由变化监听
单点登录是是什么,具体流程是什么
web网页如何禁上别人移除水印
踩坑
2025最新面试题(真实反馈)
生命周期
小程序生命周期
路由守卫
小程序不同页面传参
你做的项目
数组方法
现场给了一个题,说执行顺序
介绍一下你最近一个项目的业务流程,你负责哪些事情
权限
双签怎么做的
埋点怎么做的
小程序登录怎么做的
懒加载怎么做的
敏感信息怎么处理
多端开发怎么做的
怎么判断一个请求是h5端发起的,还是pc端发起的
你的优势是什么
与后端发生冲突怎么做
内边距,外边距是什么
前端怎么申明变量,区别
前端有哪些异步函数,怎么处理异步
你知道回掉地狱吗,有什么危害,怎么解决
怎么防止sql注入
怎么防止xss,ddos网络攻击
怎么处理大规模的并发,你之前项目中有遇到吗,讲讲场景,怎么解决的
有做过票务系统吗
有做过电商系统吗,讲讲你做的
is,ts区别
前端如何处理敏感信息
数据安全你做过哪些
有做过小程序吗
有没有做过html转译
antd有用过吗,与其他框架比感觉怎么样
前端崩溃怎么办,如何优化
diff算法
闭包
es6
双向数据绑定原理
插槽,项目中怎么用的
vuex,项目中怎么用的
懒加载有哪几种方式,具体实现
h5,移动端pc端如何适配
封装过哪些组件,考虑的点是什么
自定义指令
父子组件生命周期执行顺序
nexttick怎么用,实现原理,返回一个什么,源
码看过吗
promise(深)
async await与promise区别
axios怎么封装,如何取消请求
同源策略
cookie怎么在跨域之间共享
解决跨域的方式
项目优化
is数据类型,检测数据类型的方式
数组遍历的方法,map foreach区别
前端怎么批量处理请求并发
讲讲你印象最深刻的项目,你负责什么
面向对象,面向过程
vue是面向对象还是过程,为什么
vue页面开发是面向对象还是过程,为什么前端发请求到后端整个过程,越详细越好
前端是如何精确找到后端的,原理是什么
有没有做过项目部署
你的代理是怎么做的
chorm浏览器有哪些东西,都有什么作用一个页面有50个组件,某个组件卡了,怎么精确定位,怎么解决
优化做过哪些
响应式是什么,原理是什么,有哪些副作用有没有接触过因为响应式出现的的bug,业务场景,怎么解决的
项目的亮点,难点,怎么解决的
介绍一下你做的项目
js数据类型
es6
原型,原型链
继承,实现继承的方式
class
垃圾回收机制
evenloop
闭包
mvvm
数据绑定原理
v2 和v3区别
vuex
插槽,作用域插槽是用来干嘛的
路由守卫,用来干嘛
有没有对请求做过处理
webpack打包,有没有做过改动或者优化
cdn为什么没有跨域
如何知道一个dom在不在可是区域内
权限怎么做的
大文件上传如何实现
pdf渲染怎么做的
你会什么,你擅长什么,你有哪些不足,如何与客户去沟通,当需求频繁变更,你如何处理,当你感觉客户需求不对的时候该怎么办当你工作出错你该怎么办,有没有带过团队,能不能带团队,你之前项目多少人,你负责什人…
ts中typeof和instance区别
v3组件传值
改变this指向的方式
data为啥是个函数
大文件上传
v2和v3区别
说一下vuex
存储方式
懒加载,缓存,代码压缩等优化方案
vmodel原理,如何手写一个vmodel
数据双向绑定原理
生命周期
promise
口述深拷贝,深浅拷贝区别
es6
set干嘛的数组方法,
webpack
项目亮,难点