Q1. 说一下重排和重绘
- 重排和重绘是浏览器渲染路径上的两个节点, 浏览器的渲染路径就是DOM和CSSOM生成渲染树,然后根据渲染树来进行布局,确定页面上所有内容的大小和位置,确定布局后,将像素绘制到屏幕上。
- 其中重排就是当元素的位置发生变动的时候,浏览器重新执行布局这个步骤,来重新确定页面上内容的大小和位置,确定完之后就会进行重新绘制,所以重排一定会导致重绘。
- 如果元素位置没有发生变动,仅仅只是样式发生变动,这个时候浏览器重新渲染的时候会跳过布局步骤,直接进入绘制步骤,这就是重绘,所以重绘不一定会导致重排。
Q2. 说一下事件循环输出顺序
- 先执行同步代码
- 然后执行微任务,process.nextTick()和Promise的回调函数
- 执行单个宏任务
- 执行微任务
- 执行单个宏任务
- 循环下去
Q3. 隐藏页面元素方式及区别
- display: none, 完全消失,不占据空间,无法触发事件
- visibility: hidden, 只是隐藏该元素,还是占据空间,无法触发事件
- opacity: 0, 依然占据空间,依然可以触发事件
Q4. 水平垂直居中方式及区别
- 用flex实现: 定义父元素长宽然后设置display: flex, 并且justify-content和align-items都为center
- 用绝对布局实现: 定义父元素长宽然后设置position为relative,子元素定义position为absolute,left和top为50%,并且transform定义为translate(-50%,50%),就是向左向上移动自己一半的长度。
- flex之后margin: 父元素定义长宽然后flex,子元素margin设为auto
Q5. http状态码有哪些
- 101 协议转换
- 200 正常访问
- 301 永久重定向
- 302 暂时重定向
- 304 资源未被修改
- 401 未认证
- 403 未授权
- 404 未发现指定网址
- 500 服务器发生错误
- 504 网关错误
Q6. 判断数组方式有哪些
- Object.prototype.toString.call(var)
- Array.isArray(var)
Q7. 数组常见方法有哪些,哪些能改变数组本身?
- 能改变数组本身的有
- push()在最后新增数据
- pop()删除最后一位
- shift()删除第一位数据
- unshift() 在第一位增加数据
- reverse()反转数组
- sort()排序
- splice()删除指定位置并替换
- 其他常见的有
- concat()合并数组
- join()使用分隔符转为字符串
- slice()截取指定位置的子数组
- toString()转为字符串
- forEach()遍历数组,没有返回值
- map()遍历数组,会返回一个新函数
- indexOf()查询并返回数据的索引
- filter()过滤数组,由返回值为true的数据组成新数组
Q8. 前端本地存储有哪些?
- Cookies
- localStorage
- SessionStorage
- indexedDB
Q9. let const var 区别?
- let和const有块级作用域,var没有块级作用域
- var允许声明提前,let和const不被允许
- var可以被重复声明同名变量,let和const在一个块级作用域里不被允许
- var和let可以被重复生命,const不允许
Q10. 什么是内存泄露,哪些情况会造成?如何查看泄露情况?
- 内存泄露就是对象申请了内存,用完了又不释放,垃圾回收不能回收他们的情况
- 常见的内存泄露包括:
- 可以通过浏览器开发者工具的memory选项下去拍摄堆快照,然后分析这些快照,检查内存使用是否有意外增长,或者用一些内存分析库,也可以手动代码审查
Q11. 浏览器攻击有哪些
- 跨站脚本攻击XSS: 在网页中插入恶意脚本,使得其他用户在浏览该页面时受到攻击,敏感信息被窃取。
- 跨站请求伪造CSRF: 利用用户当前的登录状态来执行未经授权的请求。攻击者会诱导用户点击一个看似正常的链接,使用户的浏览器发送带有恶意意图的请求,从而导致攻击成功
- 浏览器插件漏洞
- 钓鱼攻击: 伪造网站或电子邮件,欺骗用户输入敏感信息
Q12. 手撕:数组去重
const arr = [1,2,3,3,4,4,4,5,1,1]
const sol1 = Array.from(new Set(arr))
const sol2 = arr => {
const res = []
arr.forEach(value => {
if (res.indexOf(value) === -1) res.push(value)
})
return res
}
const sol3 = arr => {
const res = []
arr.forEach(value => {
if (!res.includes(value)) res.push(value)
})
return res
}
const sol4 = arr => {
return arr.filter((value, index, arr) => {
return arr.indexOf(value) === index
})
}
Q13. 手撕:快速排序quick sort
def quickSort(arr, low ,high):
if low < high:
pi = partition(arr, low, high)
quickSort(arr, low, pi-1)
quickSort(arr, pi+1, high)
def partition(arr, low, high):
i = low
for j in range(low, high):
if arr[j] <= arr[high]:
arr[i], arr[j] = arr[j], arr[i]
i = i + 1
arr[high], arr[i] = arr[i], arr[high]
return i
arr = [15, 3, 1, 4, 9, 8, 2]
quickSort(arr, 0, len(arr)-1)
print(arr)
Q14. 虚拟Dom优点有哪些?虚拟Dom是如何改变结点的?
- 虚拟DOM的优点有
- 虚拟dom可以减少对实际dom的直接操作次数,提高性能
- 有一个搞笑的Diff算法,通过比较前后两个虚拟dom的差异,只更新实际dom中变化的部分,而不需要重新渲染整个页面
- 虚拟dom改变节点是通过
- Diff算法,找出新旧虚拟dom的差异,并只更新有变化的部分