秋招面试考点复习笔记

215 阅读13分钟

这些都只是简易的答案,当你发现某个标题你不是很清晰的时候,应该自己去搜索复习巩固,下面的解析只是给你一些提醒,秋招加油

闭包的理解:

闭包就是当前作用域可以访问上级作用域中的变量,导致在函数作用域中的变量在执行完之后不会被销毁

ajax,fetch,axios有什么关系?

ajax,fetch,axios都可以用来网络请求,但是是不同维度的词,什么叫不同维度的词,意思就是栈,队列跟数组之间是什么关系,逻辑和物理之间的区别

ajax是一个技术统称,类似逻辑结构,不是实际的东西,可以用某些方式来实现ajax

fetch是一个具体的api,可以在浏览器打印,fetch是浏览器原生的api,可用于网络请求,相比较XMLHttpRequest更加简洁,还支持promise,所以可以理解为XMLHttpRequest的升级版

axios是一个第三方库,最常用的网络请求lib,内部可以通过fetch和XMLHttpRequest来实现

经典题目 XMLHttpRequest封装 (XMLHttpRequest也是一个函数,在没有fetch之前都是用这个)

image.png

手写防抖和节流

image.png

image.png

  • 防抖是执行最后一个
  • 节流是执行第一个

屏幕适配单位

  • em 根据当前元素
  • rem 根据根元素
  • vw vh 屏幕的百分比
  • vmax vmin 二者中的最大值和最小值

箭头函数的一些特性

  • 箭头函数没有arguments
  • 无法通过apply,call,bind改变this 使用的父作用域的this
  • this不适用的地方:
  • 对象的方法
  • 原型链上的方法
  • 构造函数上的方法

for in 和 for of 有什么区别

for of 除了对象都可以

分别遍历key 和 value

注意:

遍历对象for in 可以,for of 不可以

遍历Map Set generator for of 可以 for in 不可以 原理:

  • for in 用于可枚举数据 如对象、数组、字符串
  • for of 用于可迭代数据 如数组、字符串、Map、set

for await...of 就是promise.all的替代品

HTMLCollection和NodeList的区别

DOM是一棵树,所有节点都是Node

Node是Element的基类

Vue computed 和 watch 有什么区别

computed:利用现有的数据计算产生新的数据 watch:用于监听现有数据

1658329529474.png

computed有缓存,method没有缓存

Vue的组件通信

props emit vue3的 适用于父子组件

自定义事件:记得销毁事件 适用于不相关的组件

$attrs 适用于上下级 作为props和emit的替补。如果这两个里面没有就在$attrs里面

v-bind="$attrs" 这样可以把所有的信息给子组件

inheritAttrs:false 不在dom元素里面 取决于是不是只有一个元素

$parent 直接 this.$parent.X 就可以获取父组件的方法和属性

$refs 加上ref就可以直接获取子组件的值 this.$refs.ref的名字.属性和方法

provideinject 属性: provide:{ info:'aaa' } inject:['aaa'] 在父辈组件上使用了provide,子组件都可以用inject的数组获取到属性 方法: provide(){ return { info:computed(()=>{this.name}) } }

严格模式有什么特点?

开启严格模式 只需要加 'use strict' 一般用于生产环境,开发环境使用

全局变量必须先声明

禁止使用with

this禁止指向window

可以使用eval 性能差,有单独的作用域

跨域请求为什么要发送options请求

1658563956265.png options请求是跨域之前的预检查,浏览器自行发起,不用我们干预,可以查看server支持什么请求方法

js内存泄漏怎么检测,场景有哪些?

垃圾会输GC

外部引用的原因导致没有垃圾回收,这是符合用户预期的

以前:引用计数法:缺点是对象里面互相引用就不好算了

现代:标记清除法: 能在根上,也就是window上可以找到的就不清除

闭包不算内存泄漏:内存泄漏是不符合预期的回收,因为闭包是符合我们预期的 但是不可以被垃圾回收

检测内存变化

控制台里面 performance

image.png

第一步清理内存 第二步开始执行

检测结果可以看heap的队内存,看见内存的变化 正常情况应该是上升下降,如果是锯齿状一直上升一般是内存泄漏

内存泄漏的场景 vue为例子(React也一样)

主要是全局变量、函数引用、定时器、dom监听、自定义事件等,销毁时没有清除

所以清除时 需要在beforeUnmount(Vue3)、beforeDestory(Vue2) 把全局变量、定时器设置为null或者clearInterval或者window.removeEventListener('resize',fn)

WeakMap WeakSet

弱引用 只能接收对象 即使是闭包的形式 也留不住,也会进行垃圾回收

浏览器和nodoejs的事件循环有什么区别?

nojs的宏任务类型和优先级不同 6个类型 timers > I/O > idls prepare > poll > check > close callbacks 微任务 process.nextTick 比其他任务都高

虚拟DOM

用js对象模拟DOM

line-height的继承

body{
    font-size:20px;
    line-hright:200%;
}
p{
    font-size:16px;
    //继承的行高是 20*200%
}
body{
    font-size:20px;
    line-hright:50px;
}
p{
    font-size:16px;
    //继承的行高是 50px
}
body{
    font-size:20px;
    line-hright:1.5;
}
p{
    font-size:16px;
    //继承的行高是 16*1.5
}
  • line-height 是百分数时,会直接继承父级的font-size
  • line-height 是分数时,会用自己的font-size*分数
  • line-height 是数字时,会直接继承

Vue 和 React 等框架的价值:

组件化

数据视图分离 数据驱动视图 这才是核心!

只关注业务数据 而不用再关心DOM变化

diff data变化 diff算法 比较vnode oldValue (vdom)

  1. data变化
  2. vnode diff
  3. 更新DOM

总结: vdom并不快 js直接操作dom才是最快的

但是数据驱动视图要有合适的技术方案

不能全部DOM重建

所以vdom才是最适合的技术方案

遍历数组 for和forEach哪个快

for更快

forEach要创建一个函数 函数要新的作用域

nodejs如果开启进程,进程如何通讯?

进程 process 线程 thread

进程,OS进行资源分配的最小单位,有独立内存空间,进程之间相互隔离,比如抖音进程和微信进程 通讯就是进程之间同意之后进行合法通讯

线程,OS进行运算调度的最小单位共享进程内存空间

js是单线程是指只有一个线程在计算

js多核是为了同时处理多个进程,最大化利用性能

打印 process.pid 可以看见进程

fork 来开启子进程

1658652796518.png

image.png

image.png 或者cluster实现 实际工作中用PM2

JS Bridge

js无法调用native API

需要通过一些特定的格式来调用

这些格式统称为JS-Bridge 例如微信JSSDK

全局注册 异步问题

URL Scheme 推荐使用

React fiber引起的关注

组建树转化为链表,可分段渲染 渲染时可以暂停,先去执行其他更高优先级的任务,等空闲时再继续渲染 那么怎么判断空闲呢? 就是requestIdleCallback requeestAnimaationFrame 每次渲染完都会执行 (dom重绘重排等) 高优 requestIdleCallback 空闲时才会执行 低优 二者都是宏任务 都需要等dom执行完之后再执行,高优先执行,低优后执行

Vue的生命周期

  • beforeCreate

  • created 这时候已经有data method 但是还没开始渲染模板

  • beforemount 编译模板 调用render生成vdom 但是还没有渲染成dom

  • mounted 完成dom渲染 组件初始化完成

  • beforeUpdate data发生变化,准备更新dom

  • update dom更新完成 注意 不要在updata中修改data 容易发生死循环

  • beforeunmontd 即将发生销毁 可移除一些自定义事件

  • unmounted

  • keep-alive 只会被创建一次,接下来就是隐藏和激活,keep-alive会缓存

Vue什么时候操作DOM最合适?

mounted和updataed都不能保证子组件全部挂载完成 this.$nextTick来操作dom

Ajax应该放在哪个生命周期?

created和mounted两个选择

created很快,ajax放在created里面可能会影响created的过程 所以优先mounted

Vue3 Composition有什么区别

setup代替beforeCreate和created

使用hooks函数的形式 如mounted改为onMounted()

Vue2 Vue3 React 三者diff算法有什么区别?

严格diff算法 时间复杂度是O3 不可用

Tree diff的优化

只比较同一层级,不跨级比较

tag不同则删掉重建 不再去比较内部细节

子节点通过key区分(key的重要性)

优化后的复杂度O(n)

React diff 仅右移

Vue2 双端比较 一共四个指针 两边往中间移动

Vue3 最长递增子序列

React为什么循环一定要key

因为有key可以移动元素,而没有的话只能删除重建

vue和react的三种路由

hash history memoryhistory(点击的时候网页的url不会变化,像组件一样切换)

移动端H5 click有300ms延迟,怎么解决?

一开始是为了双击放大

一开始是fastClick

现代浏览器在 mata里面有 content:"width=device-width" 都不会有300ms延迟

表示已经做了响应式布局,有了移动端适配

cookie和token的区别

cookie不跨域共享

SameSite:strict禁止传递cookie

例子:在网页上看了包含手机的页面,这个页面里面有京东的广告,这个页面的cookie和京东广告的cookie跨域不共享,但是当你访问京东主站的时候,京东主站就会识别到是同一个用户,于是给用户推送手机

cookie用于登录验证,存储用户标识,一般就存userID,安全和体积问题

session在服务端,存储用户详细信息,和cookie信息一一对应

cookie+session 是常见的登录验证解决方案

cookie会自动存储,token要自己存储,一般再localstorge

token一般用于json web token token存储在客户端 发起请求的时候放在Authorization

session

优点

易于删除添加用户,学习简单,原理简单

缺点

存在服务端,如果太多用户的话会占内存

多进程,多服务器时,因为进程之间不共享内存,所以不会共享session,不好同步,第一种是通过进程之间的通讯,第二种方法是需要第三方缓存(redis),把所有的session都放在redis里面,但是这是需要成本的 默认有跨域限制

token

优点

不占用服务器内存

不会影响多进程,多服务器

缺点: 用户信息存在客户端,无法快速封禁用户,可以通过建立黑名单

万一服务端密钥泄露,会暴露所有信息

token的体积比cookie更大

如何实现单点登录(SSO)

基于cookie: cookie默认跨域不共享,但是有些情况是可以跨域共享的

比如主域名相同 www.baidu.com 和 image.baidu.com baidu.com就是主域名

可以设置cookie的domain为主域名,就可以跨域共享

SSO第三方独立的

所有登录验证都重定向到SSO,SSO返回一个token,每次都带上这个token去验证都在SSO第三方服务中

Http和UDP的区别

http是应用层 tcp和udp是在传输层

http1.0 http1.1 http2.0 有什么区别?

**http1.0 **

  • 只有get post方法

**http1.1 **

  • 增加缓存策略,
  • etag cache-control
  • 支持长连接 concoction:keep-alive
  • 一次TCP多次请求
  • 断点续传
  • 中途206
  • 新增detele,put方法

**http2.0 **

  • 头部压缩
  • 多路复用
  • 一次TCP可以多次http请求
  • 服务端推送

https加密协议

非对称加密:公钥,私钥,第一次服务端把公钥传过去,客户端通过公钥产生随机码,然后用公钥加密随机码,把加密后的随机码发给服务端,服务器可以通过私钥解开加密后的随机码

对称加密:之后就用随机码来加密解密文件 中间人攻击:黑客在中间把公钥换了,这时候就需要CA证书来判断这个公钥是否正确

script中的defer和async有什么区别?

async是异步加载完之后立即执行

defer是遇到了先加载,等dom元素加载完之后再执行

1658827662075.png

前端攻击

XSS 跨站脚本攻击

黑客将js代码插入到网页内容中,渲染时执行js代码 解决方案:httponly 和 特殊字符转义

CSRF 跨站请求伪造

严格控制跨域 设置samesite 禁止第三方网页使用cookie 关键接口使用手机验证码

点击劫持

把一个按钮隐藏,诱导用户点击 预发:禁止iframe渲染

webSocket

支持端对端通讯

可以由client发起,也可以由server发起

用于消息通知,直播间讨论等

浏览器自带websocket node有ws这个包可以发起websocket

先发起http,成功之后再切换成websocket 状态码101 connection:upgrade

websocket没有跨域限制 websocket的协议名是ws://

通过send和onmessage通讯

http长轮询

客户端一直发送请求,直到等待到有消息返回,返回完之后里面再请求消息等待 设置一个timeout机制,如果再一段时间内没有返回就取消,然后再请求,总之是客户端发起的

url到页面展示的完整过程

网络请求

DNS查询 得到IP 建立TCP连接

浏览器发球HTTP请求

收到响应,得要HTML源码(一堆字符串)

解析HTML的过程,遇到静态资源还会继续发起网络请求 js css 图片等 静态资源有可能是强缓存 cache-control:max-age

解析

解析的过程就是把字符串转化为数据结构的过程

HTML构建DOM树

CSS构建CSSOM树

两者结合,形成render tree

渲染: render tree绘制到页面上

计算各个DOM的尺寸、定位,最后绘制到页面上

遇到js会执行,单线程

重绘和重排的区别

防抖节流可以减少重排

如何实现网页多标签tab通信

websocket localStorage 注意只能接受字符串 JSON.stringfy()

网页和iframe怎么通讯

发送

iframe之间的通信用windom.postMessage() 第二个参数是域名

接受

window.addEventlisten('message',()=>{})

h5页面怎么进行首屏优化

  1. 路由懒加载 适合SPA 单页应用 路由做拆分 优先保证首页加载
  2. SSR渲染页面 页面简单 如果是简单h5页面 SSR是终极方案 SSR是一个古老的技术 Nuxt.js vue Next.js React
  3. 图片懒加载
  4. 分页

后端一次性给10w条数据,怎么处理?

首先是不可能,一般后端就会分页处理,不太可能

浏览器能否处理10w数据?

js没问题,渲染到DOM的时候会非常卡顿 自定义nodejs中间层,获取拆分10w条数据,后端不处理自己处理,成本高

虚拟列表

答:只渲染可视区的DOM 其他隐藏的区域不显示,只用DIV撑起高度,随着浏览器的滚动,创建和销毁数据 只保留可视区的dom,其他的不显示

但是不好实现

一般用第三方的lib

前端常用的设计模式有哪些?并说明使用场景

工厂模式: 用一个工厂函数,来创建实例,隐藏new 例如 React createElement 函数来创建vnode

1660572507450.png

单例模式: 全局唯一的实例(无法生成第二个) 例如 vuex redux的store

1660572724190.png

代理模式: 使用者不能直接访问对象,而是访问一个代理层 在代理层可以监听get set做很多事情 例如es6 Proxy实现Vue3

装饰器模式: 原功能不变,增加一些新的功能 Decotator next.js 就是装饰器模式

观察者模式和发布订阅模式有什么区别?

观察者模式是Subject和Observer直接绑定 没有中间媒介 如addeventListen 发布订阅模式是Publisher和Observer互不认识,需要中间媒介Event channal 如EventBus自定义事件

实际工作中做过什么vue的优化?

  • v-if和v-show
  • v-if彻底销毁组件
  • v-show使用css隐藏
  • 一般情况v-if更好,不需要过度优化
  1. v-for使用key 而且key不要用index

  2. 使用computed缓存

  3. keep-alive缓存组件 用于频繁切换的组件 例如tabs

  4. 异步组件 针对比较大的组件 拆包 需要时异步加载,不需要是不加载

image.png

路由懒加载

Vue中遇到的小问题

  1. 内存泄漏: 全局变量,全局事件,全局定时器自定义事件

  2. Vue2响应式的缺陷 Vue3没有了 data新增属性用Vue.set data删除属性用Vue.delete 无法直接修改数据arr[index]=value

  3. 路由切换是scroll回到顶部 缓存列表页数据和scrollTop的值,当再次回到列表页的时候,渲染组件,执行scrollTo

捕捉vue的错误

  • 在mounted里面添加 window.error = function (msg,source,line,column,error)=>{} 只有这个可以监听到异步的报错

  • errorCaptured生命周期 监听下级组件错误,返回false阻止向上报错 vue自带的生命周期捕获错误

  • errorHandler 在main.js 全局监听错误,同时如果捕获到了会阻止到errorCaptured里面

捕捉react的错误

  • react16之后,新增了ErrorBoundary组件,监听所有下级组件的报错,只监听组件渲染时报错,不监听DOM事件、异步错误,只有在生产环境下直接显示,在线上环境会变化为降级组件UI

  • 异步错误还是跟vue的一样,用window.onerror

如果一个h5很慢,你该怎么排除性能问题?

加载渲染

前端性能指标

  • First Paint (FP) 第一次渲染
  • First Contentful Paint (FCP) 第一次有内容的渲染
  • DomContentLoaded (DCL) dom元素的渲染
  • Largest Contentfull Paint (LCP) 最大的内容渲染完成
  • Load (L)

工具:Chrome devTools performance 可以查看性能指标 network 工具:Lighthouse 评分 npm i lighthouse -g

直接 lighthouse www.xxx.com

如果是加载慢 路由懒加载 大组件异步 优化http

如果是渲染慢 优化服务端接口 优化前端内部的逻辑 参考vue和react的优化

近期遇到的难题:

  • 多选表格,一行多列
  • 描述问题:背景+现象+造成的影响
  • 问题如何被解决:分析+解决

输出['1','2','3'].map(parseInt)

转化为:

const nums = ['1', '2', '3']
const res = nums.map((item, index) => {
    // item:1,index:0  parseInt不存在0进制,所以按照10进制处理
    // item:2,index:1  1不在2~36进制范围之间,所以不符合要求,返回NAN
    // item:3,index:2  2进制符合要求,但是2进制里面没有3,所以返回NAN
    return parseInt(item, index)
})

关于promise

多个promise的交替执行,如果返回了新的promise会慢两拍

setState是同步还是异步?

在settimeout,ajax,dom里面,setState同步更新,会立刻更新值 在一般情况下异步更新,合并setState,只有最后一次会执行

我觉得setState是同步代码却是异步表现。在React合成事件和生命周期中setState都表现为异步。在原生事件监听和定时器中表现为同步。是因为React对于state的修改时一个批量处理的操作,在同一事件循环内完成所有的数据修改,提升性能

本质是同步,只不过让react做成异步的样子

因为要考虑性能,多次修改只进行一次DOM渲染

关于对象赋值

let a = {n:1} let b = a a.x = a = {n:2} console.log(a.x) {n:2} console.log(b.x) {n:1,x:{n:2}} a.x的优先值更高 image.png

let a = {}, b = '123', c = 123 a[b] = 'b' a[c] = 'c' console.log(a);

sourcemap的作用是什么?

js上线要压缩、混淆

线上的js报错信息,将无法识别

sourcemap可以解决这个问题,可以把线上的信息转化成原来的代码的位置

在webpack里面有devtool配置 devtool:"source-map" 这样run build之后就可以有map文件

SPA和MPA怎么选择?

SPA单页应用,默认Vue和React都是SPA,SPA都在一个js文件,所以会比较慢

MPA多页应用,有的页面大,有的页面小,MPA适合多种情况的页面,有的页面小用MPA比较合适