记录一下自己 “被打” 的过程😂
面试记录
2021.2.28 从前公司离职,开始了复习知识和面试的日子。记录一下自己面试的经历以及题目,常看常新,补全知识。
富途一面
Vue 组件间通信
如果是父子组件,那么可以直接通过
props
进行通信,也可以使用provide/inject
Event Bus 通过新建一个
Vue
实例使两个组件能够进行通信Vuex
拓展:Vuex 和 Vue Router 在 install 的时候发生了什么?(其实是 Vue 插件机制)
其实 Vue 通过 use() 安装插件,就是通过 mixin 混入了方法。Vuex 和 Router 都是通过在 beforeCreate 这个生命周期里把$router
和store
挂载到了 Vue 的实例上。
Vue2 和 Vue3 的生命周期和区别
Vue 2.x Vue 3.x Details beforeCreate beforeCreate 在实例初始化之后,数据观测和 event/watcher 事件配置之前被调用 created created 在实例创建完成之后立即被调用。 $el
property 不可用beforeMount beforeMount 在挂载开始之前被调用:相关的 render
函数首次被调用mounted mounted 实例被挂载后调用,此时可以使用 nextTick
和进行 DOM 操作beforeUpdate beforeUpdate 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新前访问现有 DOM,手动移除事件监听器 updated updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。 activated activated 被 keep-alive
缓存的组件激活时调用deactivated deactivated 被 keep-alive
缓存的组件停用时停用beforeDestroy beforeUmount 在销毁(卸载)组件实例之前调用。此时实例还是完全正常的 destroyed unmounted 实例销毁(卸载)后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。 errorCaptured errorCaptured 当捕获一个来自子孙组件的错误时被调用。 - renderTracked 跟踪虚拟 DOM 重新渲染时调用。钩子接收 debugger event
作为参数。此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。- renderTriggered 当虚拟 DOM 重新渲染为 triggered.Similarly 为 renderTracked
,接收debugger event
作为参数。此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键。拓展1: Vue 父子组件的渲染顺序
父beforeCreate => 父created => 父beforeMount => 子beforeCreate => 子created => 子beforeMount => 子mounted => 父mounted
拓展2: 子组件更新过程
父beforeUpdate => 子beforeUpdate => 子updated => 父updated
拓展3: 销毁过程
父beforeDestroy => 子beforeDestroy => 子destroyed => 父destroyed
浏览器渲染
浏览器渲染进程主要有 GUI 渲染线程,JS 引擎线程,事件触发线程,定时触发器线程,异步 HTTP 请求线程。
其中 GUI 渲染线程和 JS 引擎线程是互斥的。GUI 渲染线程负责渲染浏览器界面,解析 HTML 和 CSS,在负责处理 JavaScript 脚本程序的 JS 引擎线程执行时,GUI 渲染线程会暂时挂起,直到 JS 引擎空闲。
延伸1:
- 浏览器工作流程: 构建 DOM => 构建 CSSOM => 构建渲染树 => 布局 => 绘制。
- CSSOM 会阻塞渲染,只有当 CSSOM 构建完毕之后才会进入下一阶段的构建树。
- 通常情况下 DOM 和 CSSOM 是并行构建的,但是当浏览器遇到 script 标签时,DOM 构建将暂停,直到脚本执行完成。但由于 JavaScript 可以修改 CSSOM,所以需要等 CSSOM 构建完毕后再执行 JS。
- 所以如果想要首屏渲染时间缩短,就需要把 script 标签放在 body 标签底部,或者直接不要在首屏加载 JS 文件。
浏览器缓存
基本的网络请求就是三个步骤:请求,处理,响应。后端主要就是”处理”这个步骤,所以其实前端缓存就在“请求”和“响应”中进行。
当浏览器要请求资源时:
- 调用 Service Worker 的 fetch 事件
- 查看 memory cache
- 查看 disk cache:
- 如果有强制缓存且未失效,则使用强制缓存,不请求服务器。状态码全部是200
- 如果有强制缓存但已失效,使用对比缓存,比较后确定是304还是200
- 发送网络请求,等待响应
- 把响应内容存入 disk cache(如果 HTTP 头信息配置可以缓存)
- 把响应内容的
引用
存入 memory cache(无视 HTTP 头信息的配置) - 把响应内容存入 Service Worker 的 Cache Storage
this 指向问题
可以从 Reference 类型来判断 this 的指向。
首先判断出 MemberExpression 赋值给 ref,然后判断 ref 是不是一个 Reference 类型。
Reference = {
// 属性所在的对象或 EnvironmentRecord,它的值只可能是 undefined, Object, Boolean, String, Number, environment record
base,
// 属性名
name,
// 是否为 strict 模式
strict
}
// 举个栗子
var value = 1;
var foo = {
value: 2,
bar: function () {
return this.value;
}
}
console.log(foo.bar()); // 2
/*
MemberExpression 为 foo.bar
Renference = {
base: foo,
name: 'bar',
strict: false
}
所以 this = foo,该表达式输出 2.
*/
// 有操作符,逻辑运算符或逗号运算符,ref 的就不是 Reference类型,this 就是 undefined,最终的 this 会隐式转换为全局对象,所以该表达式输出 1.
console.log((foo.bar = foo.bar)()); // 1
console.log((foo.bar || foo.bar)()); // 1
console.log((foo.bar, foo.bar)()); // 1拓展1: 将 foo.bar 改成 箭头函数会怎样?
拓展2: 将 var 换成 let 或 const 又会怎样?
箭头函数和普通函数的区别
箭头函数不会创建自己的 this,它只会从自己的作用域链的上一层继承 this。
- 箭头函数没有自己的 this,它会捕获定义时自己所处的外层执行环境的 this,并继承这个 this。
- 箭头函数继承来的 this 指向永远不变
- call,apply,bind 无法改变箭头函数中 this 的指向
- 箭头函数不能作为构造函数使用
- 箭头函数没有自己的 arguments 对象
- 箭头函数没有原型 prototype
- 箭头函数不能用作 Generator 函数,不能使用 yeild 关键字
- 斐波那契函数,以及缓存优化
// 动态规划 |
Vue 数据量大的时候,如何优化
- 按需加载局部数据,虚拟列表,无限下拉刷新(可视区域)
- 大量纯展示的数据,可以使用
Object.freeze
冻结 - 还可以进行分页
图片网站 优化
首先我们分析一下图片加载存在的问题和原因:
启动页面时加载过多图片
首屏图片优先加载,等首屏图片加载完成再去加载非首屏图片
可以进行域名切分,来提升并发的请求数量,或者使用 HTTP/2 协议
部分图片体积过大
单位像素优化 - 改变图片格式,使用
webp
格式图片像素总数优化 - 裁剪大图片,减少图片体积,减少网络开销,加快下载速率
防抖节流
// 防抖 触发高频事件 n 秒内只会执行一次函数,n 秒内事件再次触发,则重新计算时间 如果你在期间一直触发,则不会触发 |
var,let,const 的区别
let/const 是使用块级作用域;var 使用的是函数作用域,且存在变量提升。
在函数外部使用 var 进行声明都会自动成为 window 对象上的一个属性。
- 暂时性死区(TDZ)
只要块级作用域内存在 let
命令,它所声明的变量就”绑定”这个区域,不再受外部的影响。
ES6 中规定,如果区块中存在 let
和 const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明前使用这些变量,就会报错。
- 闭包
能够访问自由变量的函数被称为闭包。
自由变量:在函数中使用的既不是函数参数也不是局部变量的变量。
- HTTPS 和 HTTP 的区别
- HTTPS 是 HTTP 协议的安全版本,HTTP 协议的数据传输是明文的,是不安全的,HTTPS 使用了 SSL/TLS 协议进行加密处理。
- HTTP 和 HTTPS 使用的链接方式不同,默认端口也不一样,前者是80,后者是443.
引申: 对称加密和非对称加密 使用不同密钥进行加密和解密就是非对称加密,相对的加密解密使用同一密钥的就是对称加密。
- HTTP2.0 和 HTTP1.1 的区别?多个请求在这两个协议之间的区别?如果请求的是不同主域,那么区别在哪?
HTTP2.0
- 多路复用
- header 压缩
- 服务端推送
HTTP1.1
keepalive
可以让 HTTP 重用 TCP 链接,就是所谓的长链接。
HTTP2.0 会采用多路复用,一次 TCP 连接即可,采用 HTTP 的话,如果没有设置 keepalive
那么一次请求就要建立一个 TCP 连接。
探迹一面
- 事件机制
- 事件循环
- Vue 响应式原理
- react 优化
- setState
- 数组去重
- 深浅拷贝
- get post 区别
- 前端性能优化
- call的实现
- node require
- node 怎么读文件