1. 骨架屏的原理及实现
骨架屏是什么?
应对首屏加载的渲染等待问题
Vue中构建?
- 需要一个组件做占位使用(骨架屏组件)
- 暴露一些属性:高、宽、背景、是否有闪动动画(props)
- 这是一个公用组件需要全局注册,在 vue 插件中定义
- 不同组件的骨架屏效果要手动配置,使用的时候用 v-if,v-show 控制
自动化方案?
通过puppetter
在服务端操作 headless Chrome 打开开发中的需要生成骨架屏的页面,在等待页面加载、渲染完成后,在保留页面布局样式的前提下,通过对页面中元素进行删减或增添,对已有元素通过层叠样式进行覆盖,这样在不改变页面布局的前提下,隐藏图片和文字,通过样式覆盖,使得其展示为灰色块,然后将修改后的
HTML 和 CSS 样式提取出来
2. async / await 如何以同步的方式实现异步
async / await
可以理解为Generator 的语法糖
(Generator 又依赖于迭代器 Iterator,Iterator 的思想源于单向链表),Generator 的本质是让程序执行到指定位置先暂停(yield),然后启动(next)async function
代替function*
,await
代替yield
,同时无需手写自动执行器Generator
之所以通过同步实现异步是基于它具有暂停执行和恢复执行的特性和函数内外的数据交换和错误处理时机- 而
async / await
就是语法糖,基于Generator
和自执行器
3. 为什么三次握手 / 为什么四次挥手
为什么三次握手?
三次是最少安全次数,两次不安全,四次浪费资源
为什么四次挥手?
TCP是全双工通信,客户端与服务端建立两条通道
4. 301 和 302 对 SEO 的影响
301(永久重定向),会把老地址的信息带到新地址,促进搜索引擎效果
应用场景
:域名到期,不想继续用
302(临时重定向),会把链接成绩向多个域名分摊,影响 SEO
应用场景
:做活动时,从首页跳到活动页面
5. http1.1 为什么不能多路复用
Http1.1
不是二进制传输
,而是通过文本传输
,由于没有流概念,在使用并行传输(多路复用)传递数据时,接收端在收到响应后,并不能区分多个响应分别对应的请求,所以无法将多个响应的结果重新进行组装,也就实现不了多路复用。
6. 浏览器和 Node 事件循环的区别
Node 10 以前:
- 执行完一个阶段的所有任务
- 执行完 nextTick 队列里面的任务
- 然后执行完微任务队列的内容
Node11以后:和浏览器的行为统一了,都是每执行一个宏任务就执行完微任务队列
7. 浏览器缓存机制
一、缓存位置
Service Worker
运行在浏览器背后的独立线程,可以控制缓存哪些。如何匹配,如何获取
Memory Cache
内存中的缓存,包含网页中抓取的资源,关闭 Tab,就会被释放
Disk Cache
硬盘中的缓存,读取慢,但什么都能存,比 Memory Cache 胜在容量和时效上
Push Cache
推送缓存,是 Http2 的内容,当上面三种都没有被命中时,才会被使用,它只在会话 Session 中存在,一旦结束会话,就会被释放
二、缓存策略
协防缓存
和强制缓存
8. 为什么通常在发送数据埋点请求的时候使用的是 1*1 像素的透明 gif 土图片
- 避免跨域(img 天然支持跨域)
- 相比 png 更小,对网页几乎没有影响,可以用在浏览,点击,心跳,ID颁发等
- 图片请求不占 Ajax 请求份额
- 不会阻塞页面加载,不用加入 DOM 中
9. 如何实现 token 加密
jwt 举例
- 需要一个 secret (随机数)
- 后端利用 secret 和加密算法,对playload(账户密码)生成一个字符串(token)返回前端
- 前端每次 request 在 header 中带上 token
- 后端用同样的算法解密
10. Redux 和 Vuex 的异同点
共同点:
首先两者都是处理全局状态的工具库,大致实现思想都是:全局 state 保存状态 ——> dispatch(action)——> reducer(vuex 里的 mutation)——> 生成 newState 整个状态为同步操作
区别:
最大的区别在于处理异步的不同,vuex 里面多了一步 commit 操作,在 action 之后 commit (mutation)之前处理异步,而 redux 则通过中间件处理
11. 为什么 Vuex 中的 mutation 和 redux 的 reducer 中不能做异步操作
因为异步操作无论成功还是失败都是不可预测,更改 state 必须是纯函数,纯函数可以统一输入,统一输出
12. Vue2 中响应式原理 Object.defineProperty 有什么缺陷?Vue3 的 Proxy 的优点
Object.defineProperty
无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应Object.defineProperty
只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy
可以劫持整个对象,并返回一个新的对象Proxy
不仅可以代理对象,还可以代理数组,还可以代理动态增加的属性
13. react-router 里的 Link 标签和 a 标签有什么区别
Link 的本质也是 a 标签,只不过在 Link 中禁用了 a 标签的默认事件,改用 history 对象提供的方法进行跳转
14. Vue 渲染大量数据时应该怎么优化
- 按需加载局部数据,虚拟列表,无限下拉刷新
- js 运行异步处理:分割任务,实现时间切片处理,类似 react fiber,每次执行记录时间,超过一定执行时间则
settimeout
或requestAnimation
推迟到下一个时间片,一般一个时间片为 16ms- 利用 SSR
- 大量纯展示的数据,不需要追踪变化,用 object.freeze 冻结
15. npm 模块安装机制
- 发出
npm instal
l 命令- npm 向
registry
查询模块压缩包的网址- 下载压缩包,存放在
~/.npm
目录- 解压压缩包到目前项目的
node_modules
目录
16. webpack 热更新原理
每个模块都有个名称,当文件内容改变时,通过建立好的
socket
通知浏览器;然后页面端的webpack
脚手架代码会重载
这个模块
17. CSS 会阻塞渲染吗?
link 加载不会,但生成 CSS 规则会
18. TCP 滑动窗口策略,具体说说,它有什么好处,实现机制
窗口:发送者发送的连续字节序列的集合
滑动:发送的窗口可以随发送过程而变化
为什么需要窗口:不必每一个段进行一次确认应答,而是以一个窗口的大小进行确认。减少往返的时间,提高速度。(TCP 在发送时其实是以字节为单位的)
窗口控制和重发机制:
- 数据已到达对端,但确认 ack 丢失,折中情况是不需要重发的。如果没有使用窗口机制则需要重发。某一个 ack 丢失,在窗口机制下可以通过下一个确认 ack 进行应答。在滑动窗口下,就算某些应答丢失也不会重发
- 某个报文段丢失,一直重发发送确认 ack,但对端改发送的还在发送。如果发送方连续收到3次同一个确认 ack,就会重发数据。但是此时数据已经乱序,这就是快速重发
滑动窗口的功能:
- 保证数据的可靠传递;未确认的数据必须被发送方缓存起来;确认的数据将会移除缓存区
- 保证数据的有序传输;乱序的数据必须被接受方缓存起来
- 提供 End-to-End 的流控机制;发送方发送太快就必须阻塞等待
19. 进程是如何调度的
进程切换,本质是 CPU 资源占用者间的切换
处理机调度涉及两个方面:
- 选择进程:从就绪队列中挑选下一个占用 CPU 运行的进程
- 选择 CPU 资源:从多个可用 CPU 中挑选就绪进程可使用的 CPU 资源
进程调度的方式:
- 先来先服务调度算法
- 短作业优先调度算法
- 优先级调度算法
- 高响应比优先调度算法
- 时间片轮转调度算法
- 多级反馈队列调度算法
20. 受控组件和非受控组件
一、受控组件
- 表单元素依赖于状态,表单元素需要默认值实时映射到状态的时候,就是受控组件,这个和双向绑定相似
- 受控组件,表单元素的修改会实时映射到状态值上,此时就可以对输入的内容进行校验
- 受控组件只有继承 React.Component 才会有状态
- 受控组件必须要在表单上使用 onChange 事件来绑定对应的事件(通过 setState 方法更新 state)
二、非受控组件
- 在虚拟 DOM 节点上声明一个 ref 属性,并且将创建好的引用赋值给这个 ref 属性,react 会自动将输入框中的值放在实例的 ref 属性上
- 非受控组件在底层实现时是在其内部维护了自己的状态 state,这样表现出用户任何值都能反映到元素上
三、输入流程
- 非受控组件:
用户输入 A => input 中显示
- 受控组件:
用户输入 A => 触发 onChange 事件 => handleChange 中设置 state.name='A' => 渲染 input 使它的 value 变成 A
21. Vue 2 和 Vue 3 父子组件传参的区别
父传子:
- vue2 中父传子,父组件通过
自定义属性
发送,子组件通过props
接收- vue3 中不同的是,父组件中引入子组件后,
不需要注册
可直接只用,子组件中通过defineProps
方法接收子传父:
- vue2 中子传父,子组件通过
$emit
发送,父组件通过自定义事件
接收- vue3 中不同的是,父组件中引入子组件后,
不需要注册
可直接使用,子组件中通过defineEmits
方法发送
22. URL 结构
协议 + 域名 + 端口 + 目录 + 锚文件 + 参数
23. 编译型语言与解释型语言的区别,JS 属于哪个
- 解释型语言的翻译工作发生在代码执行时
- 编译型语言的翻译工作发生在代码执行之前
JS 是解释型语言
24. Vue 大文件上传方法
切片上传
上传思路:
- 针对文件内容生成的唯一的 hash 值,作为文件名称。确保相同文件,不同的文件名的情况下,生成的 hash 值是一样的
- 将大文件切成若干个小的分片,并且每一个分片的命名格式为“文件hash值+当前切片索引值”,方便后端合并这些切片
- 上传之前 ,将当前文件的hash值传递给后台,拿到当前文件在数据库里已经存在的切片,如果有切片已经存在,那么前端就不传递这些了,这就是断电续传的原理
- 上传过程中,通过监听当前传递的切片数除以切片总数,获取当前上传进度。当进度条百分之百时,自动通知后端将这些文件合并
- 上传完成
25. 移动端和 PC 端适配方案
一、关于移动端适配方案
- 静态布局
- 流式布局(使用 % 定义宽度,高度使用 px 固定)
- flex 弹性盒子布局
二、关于移动端兼容问题
- 通过响应式或页面终端判断去实现一套资源适配所有终端
- 通过终端判断分别调取两套资源以适配所有终端
26. 怎么做不同浏览器之间的兼容,主要是 IE 和 其他浏览器之间的兼容问题
W3C 对标准的推进,带来了不同内核浏览器的出现 从浏览器内核角度来说,浏览器兼容问题可以分为三类:
- 渲染相关
- 脚本问题
- 内核层面的问题
document.formName.item('itemName')问题
- 问题说明:IE下,可以使用 document.formName.item(“itemName”) 或 document.formName.elements [ ’ elementName’ ];Firefox 下,只能使用
document.formName.elements [ ‘elementName’ ]- 解决方案:统一使用 docuement.formName.elements [ ‘elementName’ ]
集合类对象问题
- 问题说明:IE下,可以使用()或 [] 获取集合类对象;Firefox 下,只能使用 [] 获取集合类对象
- 解决方案:同意使用 [] 获取集合类对象
自定义属性问题
- 问题说明:IE 下,可以使用获取常规属性的方法来获取自定义属性,也可以使用 getAttribute() 获取自定义属性;Firefox下,只能使用 getAttribute() 获取自定义属性
- 解决方案:统一通过 getAttribute() 获取自定义属性
eval('idName') 问题
- 问题说明:IE下,可以使用 eval(‘idName’) 或 getElement(‘idName’) 来取得 id 为 idName 的 HTML 对象;Firefox 下,只能使用 getElementById(‘idName’) 来取得 id 为
idName 的HTML 对象- 解决方案:统一用 getElementById(‘idName’) 来取得 id 为 idName 的 HTML 对象
变量名与某 html 对象的 id 相同的问题
- 问题说明:IE下,HTML 对象的 ID 可以作为 document 的下属对象变量名直接使用,Firefox 下则不能;Firefox 下,可以使用与 HTML 对象 ID 相同的变量名,IE 下则不能
- 解决方案:使用 document.getElementById(‘idName’) 代替document.idName 。最好不要取 HTML 对象 ID 相同的变量名,以减少错误;在声名变量时,一律加上 var 关键字,以免歧义
const 问题
- 问题说明:Firefox 下,可以使用 const 关键字或 var 关键字来定义常量;IE 下,只能使用 var 关键字来定义常量
- 解决方案:统一使用 var 关键字来定义常量
input.type 属性问题
- 问题说明:IE 下 input.type 属性为只读;但是 Firefox xia input.type 属性为读写
- 解决方案:不修改 input.type 属性。如果必须要修改,可以先隐藏原来的 input,然后在同样的位置再插入一个新的 input 元素
window.event 问题
- 问题说明:window.event 只能在 IE 下运行,而不能在 Firefox 下运行,这是因为 Firefox 的 event 只能在事件发生的现场使用
event.x 和 event.y 的问题
- 问题说明:IE 下,event 对象有 x、y 属性,但是没有 pageX 和 pageY 属性; firefox 下,event对象有 pageX,pageY 属性,但是没有x,y属性
- 解决方案:var myX=event.x? event.x:event.pageX; var myY=event.y? event.y:event.pageY
event.srcElement 问题
- 问题说明:IE 下,event 对象有 srcElement 属性,但是没有 target 属性;Firefox 下,event 对象有 target 属性,但是没有 srcElement 属性
- 解决方案:使用 srcObj=event.srcElement ? event.srcElement ? event.srcElement : event.target
window.location.href 问题
- 问题说明:IE或者Firefox2.0.x下,可以使用 window.location 或 window.location.href; Firefox 1.5.x 下,只能使用 window.location
- 解决方案:使用 window.location 来代替 window.location.href ,当然也可以考虑使用locaiton.replace()方法
27. JS 如何模拟多线程
轮转时间片;
短时间内轮流执行多个任务片段
28. encoding 的意义
encoding 是将信息分类的结果用一种易于被计算机和人识别的符号体系表示出来的过程,是人们统一认识、同意观点,相互交换信息的一种技术手段。
29. 网站高并发大流量访问的10个处理及解决方案
- 硬件升级
- 负载均衡
- 服务器集群
- 数据库读写分离
- 数据库分表技术(垂直分割,水平分割)
- 表建立相应的索引
- 页面静态化
- 缓存技术(MemCache,Redis)
- 禁止外部盗链
- 控制大文件的下载
30. 用户白屏如何做系统的性能分析
一般白屏现象主要观察内存和显存的使用情况
- 内存溢出
- 内存泄漏
- 显存不足,显存溢出
- CPU 利用率满载
- GPU 利用率满载
- 浏览器内核版本低
- 浏览器没开硬件加速
31. 网络攻击有哪些
一、主动攻击
- 篡改信息
- 伪造
- 拒绝服务
二、被动攻击
- 流量分析
- 窃听
32. 阻塞和非阻塞
- 阻塞:为了完成一个功能,发起一个调用,
如果不具备条件的话则一直等待,直到具备条件则完成
- 非阻塞:为了完成一个功能,发起一个调用,
具备条件直接输出,不具备条件直接报错返回
33. 如何阻止浏览器的缓存
- 添加版本号或时间戳
- 设置缓存控制头
- 使用 meta 标签
34. CSS 实现 0.5 的边框
定位+缩放
(利用 transform 缩放同时将伪元素覆盖整个 div 元素)box-shadow
(扩散半径设置为 0.5 px)- 直接使用
border
- 渐变线性
linear-gradient
35. 除了 try catch 还有什么兜底的异常捕获方法
一般使用 UncaughtExceptionHandler 处理未捕获的异常
36. nodejs 是单线程还是多线程
nodejs 是点线程
37. HashMap,HashTable,HashSet,TreeMap 的时间复杂度
都是基于散列函数,时间复杂度 O(1)
38. Scripts 的加载方式
- 同步加载:scripts
- 延迟加载:scripts defer=‘defer’
- 异步加载:scripts async=‘async’
39. import 和 link 的区别
一、本质的区别
link 属于HTML标签,而 @import 完全是 css 提供的一种方式
二、加载顺序的区别
当一个页面被加载时,link 引用的 css 会同时被加载,而 @import 引用的 css 会等到页面全部被下载完再被加载
三、兼容性的差别
@import 是 css 2.1 提出的,所以老的浏览器不支持,@import 只有在 IE5 以上的才能识别,而link 标签无此问题
四、使用 dom
当使用 JavaScript 控制 dom 去改变样式的时候,只能用 link 标签,因为 @import 不是 dom 可以控制的
40. 版本管理工具
一、应用场景
- 备份
- 代码还原
- 协同开发
二、版本控制器的方式
集中式版本控制工具 SVN
- 集中式版本控制工具,版本库是集中存放在中央仓库的,每个人都必须在中央服务器下载代码,是必须要连接公司的内网才能工作的,个人修改后然后提交给中央版本库。但是缺点很严重,如果公司人员过多,并且在早上同时都要从中央服务器下载代码,这就能导致中央服务器容易宕机。主要有:SVN
分布式版本控制工具 Git
- 分布式版本控制系统没有中央服务器,每个人的电脑上都是一个完整的版本库,这样工作的时候,无序连接公司的内网,就可以在自己的电脑上下载,并且有云版本托管平台,用于多人协作,只需要将代码传送到云平台(Github,gitee),其他人就可以进行拉取过来,共同使用。主要有 Git
41. 前端工程化的理解
狭义上的理解
:将开发阶段的代码发布到生产环境,包含:构建、分支管理、自动化测试、部署
广义上的理解
:前端工程化应该包含从编码开始到发布、运行和维护阶段一切以提高效率、降低成本、质量保证为目的的手段都属于工程化
工程化主要解决的问题?
- 传统语言或语法的弊端(es6、es7 等新特性,sass、less 预编器等)
- 无法使用模块化 / 组件化
- 重复的机械式工作
- 代码风格统一、质量保证
- 依赖后端服务接口支持
工程化包含的内容:
模块化
、组件化
、规范化
、自动化
42. webpack 的理解
webpack 是目前前端工程化最佳的方案
- 针对一个项目依赖多个模块的场景,行业里提出了模块化的方案,而 webpack 能够推广,本质上是因为他是一个典型的优秀的模块化方案
- webpack 在打包过程中,loader 会将浏览器看不懂的代码翻译为浏览器看得懂的,更高级的功能由 plugin 来辅助
- plugin 和 loader 都是可拔插的,意思是需要它的时候插进来,不需要的时候再删掉
43. TCP 丢包重传机制
- 发送方将数据分成若干个数据包,并且每个数据包都有一个序号
- 接收方收到数据包后,会发送一个确认消息,表示已经收到了数据
- 如果发送方没有收到确认消息,就会认为数据丢失了,会重新发送该数据包
- 如果接收方收到了重复的数据包,就会发送一个重复确认,表示已经收到了该数据包
- 发送方收到重复确认后,会认为该数据包已经被接收方收到了,不需要再次发送
- 如果发送方连续多次重传同一个数据包,就会被认为网络出现了问题,会减慢发送速度,以避免网络拥塞
44. 什么是 HTML?什么是 CSS?
一、什么是 HTML
HTML 就是超文本标记语言。“超文本”就是表示页面可以包含非文字元素,如:图片、链接、音乐等等,它是一种建立网页文件的语言,通过标记式的指令,将影像、声音、图片、文字等链接显示出来,这种标记性语言是因特网上网页的主要语言
二、什么是CSS
CSS 值层叠样式表
45. 前端安全
一、XSS 跨站脚本攻击
- 原理:攻击者想尽一切办法,将可执行的代码注入到我们的页面中,让页面进行一些非法操作(存储型、反射型)
- 防御方式:
转义字符
二、CSRF 跨站请求伪造
- 原理:获取用户个人信息去访问别的网页
- 防御方法:
SameSite 限制第三方 Cookie
验证 Referer 验证发起请求的页面是不是我们的系统
Token 发送一个带有过期时间的 token
三、SQL 脚本注入
- 防御方法:
增加黑名单或白名单验证
安全检测
防止系统敏感信息泄漏
四、上传漏洞
- 防御方法:
客户端校验
服务端校验
46. vue 虚拟 DOM 和真实 DOM 有何区别
- 虚拟 dom 不会进行重排、重绘、虚拟 dom 是把 js 代码转化为真实 dom
- 真实 dom 频繁回流和重绘效率非常低
- 虚拟 dom 可以跨平台操作而真实 dom 是与浏览器绑定的
- 虚拟 dom 进行频率修改后,一次性在真实 dom 中更新,减少损耗
47. vue 的 API
全局 API
Vue.extend (options)
用于创建一个“子类”Vue.set (target,key,value)
用于设置某个实例对象的属性值Vue.delete (target,key)
Vue.directive (id,[definition])
Vue.filter (id,[definition])
Vue.component (id,[definition])
Vue.mixin (mixin)
48. 3XX,4XX
- 301 永久重定向
- 302 临时重定向
- 304 未修改
- 401 未授权
- 403 禁止
- 404 未找到
49. 为什么选择使用 vuex,而不直接存入内存中
- vuex 可以监听数据的变化
- 可以存储任意形式的数据
- 可以进行模拟化存储
- 没有数据存储大小限制
50. 后端如何取得 cookie 中的内容
使用 springboot 框架,在 controller 层取得 cookie 在接口函数中增加参数 HttpServletRequest
request,即可用 request.getCookies() 函数获取 cookie