面试复盘(三):第一次电话面试「无力」

1,135 阅读7分钟

面试复盘系列第三篇,怎么越面感觉越差了呢?开始怀疑自己,怀疑人生...

这次面试之后,停下了投简历、面试的脚步。学习整理、刷leetcode,结合项目做更多的思考和沉淀✊...

概况

  • 公司:坐标上海,电商类业务。
  • 面试官:严肃认真的女面试官。
  • 面试结果:未通过。
  • 面试感受:坐在广场上电话面试「紧张」,旁边一个小孩子在和奶奶讲话,我一句都没听见。

面试题

  1. 介绍一个你做得最好的项目。8
  2. 前端控制路由,如果只是在前端控制路由,用户随便输入一个地址,后台需要接口判断,会存在先跳到页面再跳转到登录页面?7 ✔
  3. vue生命周期,详细讲解一下。created和mounted周期的区别,哪个更适合请求后台数据?8 ✔
  4. computed和watch区别?6 ✔
  5. 移动端适配方案?rem布局具体实现?7 ✔
  6. cookie、localStorage、SessionStorage 9 ✔
  7. preload 和 prefetch 7 ✔
  8. 性能分析 6 ✔
  9. undefined 和 null 的区别 9 ✔
  10. ES6新增的数组操作方法 「脑子突然短路😵,没说出来几个 」 6 ✔

问题2 路由控制

除部分路由如login,其他路由必须登录过(有token、知道用户角色)。可以放到beforeEach路由守卫里判断当前路由角色权限,是否包含当前用户。

问题3 vue生命周期

  1. new Vue(),初始化事件和生命周期
  2. beforeCreate($el和data都是undefined)
  3. 初始化数据和方法(data和props的响应式处理,mehods方法声明)
  4. created($el是undefined,修改data不触发update)
  5. 判断有没有el项(vm.$mount(el)),判断有没有模板(没有将el外层的HTML当模板),将模板编译成渲染函数,返回虚拟DOM
  6. beforeMounted($el是虚拟DOM,修改data不触发update)
  7. 创建正式DOM替换虚拟DOM,挂载到页面指定容器显示
  8. mounted(可操作真实DOM)
  9. 数据变更
  10. beforeUpdate
  11. 重新渲染虚拟DOM并通过DIFF算法比较差异更新真实DOM
  12. updated
  13. 调用vm.$destory()
  14. beforeDestory(清理计时器、事件)
  15. 移除数据监听、事件监听和子组件
  16. destoryed(实例不可用)

created vs mounted

created和mounted时间差为几十ms,异步请求返回花费的时间一般都会比这个差值长,所以都会引起页面的重新渲染。只是created会早几十ms。

问题4 computed和watch

computed计算属性,是基于他的响应式依赖进行缓存的,只有相关响应式依赖变更才会重新求值。多次访问计算属性或立即返回之前的计算结果,不会再次执行函数。(即时重新渲染时使用缓存,相比而言方法会在每次重新渲染时调用)

watch侦听器,更适用于监听数据变化是执行一些异步操作或其他逻辑处理,watch还可以设置deep为true,实现对象属性的深度监听(嵌套多深都可以)。

值得注意的一点,不要使用箭头函数定义watcher函数,平时的vue项目里使用箭头函数,this指向undefined,html中script引入vue这种this指向window。

问题5 移动端适配方案

px+flex方案

一些场景可能希望手机越大,看到的内容越多,可以直接使用px。不过元素、图片布局的适应需根据业务需求来做。

rem布局

通过html根元素进行适配,1rem=1根元素字体大小,根据不同屏幕使用CSS媒体查询或JS设定根元素的大小。

px2rem,可以自己写方法,也可以使用依赖包px2rem。

vw布局

依赖包,postcss-px-to-viewport

vw + rem布局

1vw = 视口宽度 * 1%

如根元素的大小,使用vw,其他元素布局使用rem。

viewport

移动端必须设置viewport,@media才能拿到符合视觉宽度的尺寸。

  • layoutviewport:布局视口,大于实际屏幕。
  • visualviewport:可见视口
  • idealviewport:理想视口,设备尺寸

问题6 cookie、localStorage、SessionStorage

  1. 数据存储方面:cookie在同源的HTTP请求里,在服务器和客户端来回传递。storage是本地保存。
  2. 存储数据大小:cookie限制4kb,storage约5MB。
  3. 数据有效期:cookie的有效期与过期时间设置有关(默认是会话),sessionStorage 当前标签页有效,localStorage始终有效。
  4. 作用域:cookie、localStorage同源窗口,sessionStorage当前标签页
  5. 操作:cookie只作为document的一个属性可获取,没有其他操作方法。storage邮getItem\setItem\removeItem\clear等方法。

问题7 preload和prefetch

preload

让浏览器提前加载指定资源(不执行,多为当前页面的资源),不阻塞渲染和document的onload时间。

preload会提升资源加载的优先级(一定加载,不管有没有遇到资源依赖)。

跨域文件preload,需要加上 crossorigin属性。(跨域不加crossorigin的preload请求缺少origin字段)

prefetch

告诉浏览器可能需要的资源(下一个页面的资源),不一定会加载。

preload、prefetch混用,不会复用资源,会重复加载。

import(/* webpackPreload: true */ 'ChartingLibrary');
import(/* webpackPrefetch: true */ 'LoginModal');
<!--type提示MIME类型,crossorigin处理跨域-->
<link rel="preload" href="sintel-short.mp4" as="video" type="video/mp4">
<link rel="preload" href="fonts/cicle_fina-webfont.svg" as="font" type="image/svg+xml" crossorigin="anonymous">
<!--响应式预加载-->
<link rel="preload" href="bg-image-narrow.png" as="image" media="(max-width: 600px)">
<link rel="preload" href="bg-image-wide.png" as="image" media="(min-width: 601px)">

加载优先级:

  1. Highest:html、css、font
  2. High:JS(直接引入、preload)、font(preload)
  3. Low:JS(异步加载 async)
  4. Lowest:css/js(prefetch)

async:异步加载js文件,如果浏览器空闲并且load事件触发,会在load事件触发前执行。

defer:异步加载js文件,脚本延迟到文档解析、显示之后执行,效果与window.onload类似。

问题8 性能分析

  • chrome开发工具的network面板,有waterfall(Timing),有TCP连接 queueing事件,请求发送requres sent时间,TTFB服务器处理返回的时间,content download时间。
  • chrome插件,lighthouse,检测页面性能,生成报告,提交优化建议。
  • performance API:timing字段如下
{
  "navigationStart": 1599730498850,
  "unloadEventStart": 1599730499155,
  "unloadEventEnd": 1599730499156,
  "redirectStart": 0,
  "redirectEnd": 0,
  "fetchStart": 1599730498852,
  "domainLookupStart": 1599730498852,
  "domainLookupEnd": 1599730498852,
  "connectStart": 1599730498852,
  "connectEnd": 1599730498852,
  "secureConnectionStart": 0,
  "requestStart": 1599730498854,
  "responseStart": 1599730499151,
  "responseEnd": 1599730499163,
  "domLoading": 1599730499172,
  "domInteractive": 1599730499517,
  "domContentLoadedEventStart": 1599730499518,
  "domContentLoadedEventEnd": 1599730499525,
  "domComplete": 1599730501370,
  "loadEventStart": 1599730501370,
  "loadEventEnd": 1599730501373
}

问题9 null和undefined

相同点:

  • 都是一种基础数据类型,且该类型只有一个值
  • 布尔转换都是false,undefined == null √
  • 没有属性和方法

不同点

  • undefined不是关键字,null是
  • undefined未初始化,null已初始化
  • typeof undefined结果是undefined,typeof null结果是Object
  • Number(null) 0,Number(undefined) NaN。

问题10 ES6数组操作方法

  • includes、fill、find、findIndex
  • entries、keys、values(用的比较少,Object.entries/keys/values用的比较多)
  • copywith、flat、flatMap

**Array.from:**把两类对象转换成真正的数组,一类是类似数组的对象(array-like,像HTMLCollection、NodeList集合、arguments对象),另一类是可遍历的对象(包括ES6的Set和map)。所有部署了Iterator接口的数据结构。

Array.from与拓展运算符的区别

  1. Array.from还支持类似数组的对象,如Array.from({length:2}),返回[undefined, undefined]。
  2. Array.from支持第二个参数,类似数组的map方法。

Array.of:将一组值转换成数组。区别于 Array() 或 new Array() ,Array(3) 得到的是 [ , , ],Array.of(3) 得到的是 [3]。

系列文章

面试复盘(一):面试官「前阿里大佬」果然厉害

面试复盘(二):希望可以获得简单直接的回答