2022前端复习

董俊豪
2022-02-25 / 0 评论 / 0 点赞 / 641 阅读 / 21,037 字
温馨提示:
本文最后更新于 2023-12-11,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

https://zhuanlan.zhihu.com/p/308705887
面试复习必读

一、javascript基础

1.介绍执行上下文
它是javascript代码解析和执行时所在环境的抽象概念,
有三种执行上下文类型,全局 函数和eval,创建执行上下文包含创建阶段和执行阶段
(1)创建阶段 this绑定、词法环境组件、变量环境组件
词法环境是一种持有标识符—变量映射的结构
变量环境是持有变量声明语句
(2)执行阶段 执行这些变量的分配
多个上下文构成ecs 后进先出执行调用栈
2.作用域链
作用域链是由多个执行上下文变量构成的链表,它规定代码执行时如何查找变量,一直找到全局上下文的变量对象,确定当前执行代码对变量的访问权限
3.闭包
函数内部定义了其他函数,内部函数可以访问外部函数的参数或者变量;本质是内层函数的堆地址暴露
主要用途:读取函数内部变量,让变量始终保存在内存中
应用 单例设计模式,函数防抖 私有变量方法
4.this
函数运行时 根据执行环境绑定内容,表示当前执行上下文
函数的运行环境到底怎么决定,它跟内存数据结构有关
默认绑定 隐式绑定,显示绑定
new绑定=显示绑定>隐式绑定>默认绑定
箭头函数不使用this四种标准,而是根据外层作用域决定this
5.如何实现call apply
分绑定this 实现传参两部分,
参数部分 先判断是否为null 或者undefined,然后定义一个新数组,遍历arguments,然后将this绑定this将this赋值给自定义fn,执行fn 然后delete

var name = '1';
  var obj ={
  name:'2'
}
Function.prototype.call_ = function(obj){
  obj = obj ? Object(obj) : window;
  var args = [];
  for(var i = 1,len = arguments.length;i<len;i++){
    args.push("arguments["+ i +"]")
  }
  obj.fn = this;
  eval("obj.fn("+ args +")");
  delete obj.fn;
}
Function.prototype.call_ = function(obj){
  obj = obj ? Obejct(obj) : window;
  obj.fn = this;
  let args = [...arguments].slice(1);
  let result = obj.fn(...args);
  delete obj.fn
  return result
}

Function.prototype.call_ = function (obj, arr){
  obj = obj ? Object(obj) : window;
  obj.fn = this;
  let result;
  if(!arr){
    result = obj.fn()
  } else{
    result = obj.fn(...arr)
  }
  delete obj.fn;
  return result;
}

6.如何实现一个bind

if(!Function.prototype.bind){
  Function.prototype.bind === function(oThis){
    if(typeof this !== 'function'){
      return
    }
    let self = this
    let args = Array.prototype.slice.call(arguments,1))
    let fBound = function(){
      let _this = this instanceof self ? this : oThis
      return self.apply(_this,args.concat(Array.prototype.slice.call(arguments)));
    }
    if(this.prototype){
      fBound.prototype = this.prototype
    }
    return fBound
  }
}

7.介绍一下javascript原型
js的继承通过prototype 原型对象实现,原型对象的所有属性和方法可以被实例共享
原型对象的属性不是实例自身的属性,修改原型对象 所有实例会对应修改
构造函数可以视为新建对象的模板
所有对象可以追溯到Object.prototype 然后它的原型是null
instanceof 运算符返回一个布尔值,表示对象是否是某个构造函数的实例
Object.create(null); 创建一个原型为null的干净对象。
__ proto __ constructor是对象独有,prototype是函数独有

除了箭头函数,其他所有函数都是构造函数,所有构造函数默认有prototype属性,它指向一个对象,被指向的对象默认有constructor,叫原型对象
所有对象都是由构造函数创造,所有对象都有[[prototype]]隐藏不可直接打印、__proto__可直接打印,再加上构造这个对象的函数的prototype,这仨指向同一个对象,被这仨指向的对象叫原型对象

8.Promise是什么
Promise是一个对象,是一种异步编程的解决方案,可以获取异步操作的消息, 有pending fulfiled rejected三种状态,可以调用.all .race .any .allSetted
all 任意一个reject立即结束,返回第一个reject的返回值
allsetted 返回错误时还可以继续等待结果,会等所有结果返回后按照传参传入的顺序返回promise结果 status value
any 任意完成,则返回完成,全部reject才reject
race 任意完成或reject则返回
9.如何实现Promise+
一、实现resolve rejected回调方法
二、.then链式调用
10.async await
async声明一个function是异步的 将后面的函数返回Promise对象,await 等 待异步方法执行完成,等待Promise完成 将返回的resolve作为结果返回
多个请求方法,可以用Promise.then 串行调用,或者async await
11.深浅拷贝
基本数据类型复制在栈内存开辟,不会相互影响
引用数据类型在堆内存,深拷贝在堆内存开辟新空间,前拷贝指向同一个堆空间
slice 和concat在一维数组可以深拷,返回新数组

将函数的实际参数转换成数组的方法
方法一 : var args = Array.prototype.slice.call(arguments);
方法二: var args = [].slice.call(arguments);
12.如何实现深拷贝
可以用JSON.parse(JSON.stringify) function或者RegExp不可
一维引用数据类型可以用slice concat,es6 ...扩展运算符
for in
Object.assign() 将可枚举的属性值复制到目标对象,深浅拷贝根据 复制的值的数据类型判断
递归实现方式 lodash.cloneDeep()
13.解决循环引用问题
使用weakMap结构,存储已经拷贝对象 vuex deepclone
map.get(obj)
map.set(obj.result
14.事件循环
是js执行调用任务事件顺序的机制,首先js的执行引擎是单线程,同步任务直接进入执行栈,同步事件执行完之后进入消息队列,消息队列分宏任务,微任务,常见宏任务setTimeout setInterval,常见微任务Promise process.nextTick(),先执行微任务,后执行宏
任务,有事件回调就进入主线程执行,消息队列执行完之后执行下一次事件,直到没有任务。
所有同步任务在主线程执行,js运行时创建执行栈,
主线程之外存在消息队列,异步操作完成就到消息队列排队
js执行引擎单线程,不会开辟新的线程,同步任务直接进入执行栈,异步任务进入消息队列
消息队列分为宏队列 微队列
15.service worker
服务器和浏览器之间的中间人角色,拦截请求进行判断,如果可以使用缓存就返回缓存数据,否则转给服务器,提高浏览体验
16.web worker
为javascript创建多线程环境,主线程运行时将一些任务分配给web worker,独立于主线程运行,运行结束后将结果返回主线程

二、CSS

1.Flex 弹性布局
flex-grow: 1; /* 设置在子元素上,剩余空间,子元素按1/n的比例进行拉伸 */
Flex 默认 0 1 auto 不放大会缩小
flex:0; 0 1 0% 不放大会缩小 最小内容宽度 一柱擎天
flex:none; 0 0 auto 不放大不缩小 最大内容宽度不会换行 设置按钮 *
flex:auto 1 1 auto 会放大会缩小 优先放大
flex:1; 1 1 0% 会放大缩小 优先牺牲自己宽度 等比平分 *

.grid{
display: grid;
grid-template-columns: repeat(3, 1fr); /* 相当于 1fr 1fr 1fr /
grid-template-rows: repeat(3, 1fr); /
fr单位可以将容器分为几等份 /
grid-gap: 1%; /
grid-column-gap 和 grid-row-gap的简写 */
grid-auto-flow: row;
}

flex 是flex-grow、flex-shrink、flex-basis的缩写
flex-grow 指定了拉伸因子
flex-shrink 指定了收缩的规则
flex-basis 指定了flex元素在主轴方向上的初始大小
flex:auto 使得盒子的宽度由盒子内容决定,flex:1 宽/高 一致
2.移动端1px处理
几个特定的媒体查询,设置0.5,flexible.js 手机淘宝团队的适配方案
3.介绍一下rem vw
rem相对html根结点font-size,
1vw 1vh等于 视口1%
4.重绘 重排
重绘是元素外观改变触发浏览器重绘,背景颜色 字体颜色
重排 元素添加删除 放大缩小移动,动画 边框,浏览器resize 窗口尺寸改变
避免多层内联样式,运用BFC 尽量避免calc计算数据
5.Less/Sass
Sass Ruby
环境 功能更强大,变量、函数作用域、条件语句、输出设置、 使用$ @mixin xxx($value:10px){} @include xxx(20px) 重用代码块
Less使用@

三、Vue React

1.介绍MVVM 和MVC区别,ViewModel有什么好处
是程序设计的一种架构模式,封装程序设计过程需要关注的地方,模块化管理提升软件质量,具体单Model通知多视图更新数据,
MVVM是从MVP模式改良来的,ViewModel可以更新并响应持续的View,View层跟着Model同时变更,
它能让View层可组件化,简化测试,提升可维护性
运行机制2.0 3.0对比:
https://juejin.cn/post/6844904099704471559
3.Nexttick如何实现
需要在dom挂载到页面之后再进行页面更新的操作,echarts、视频、音频、第三方
原理使用浏览器的setTimeout 微任务的特性,实现nexttick的队列
4.父子组件生命周期顺序
父beforeCreate->父created->父beforeMount->子beforeCreated->子created->子beforeMount->子Mounted->父mounted
5.双向绑定如何实现
考虑4个问题,怎么监听View、怎么监听Model、View变化怎么更新到Model、Model变化怎么更新到View
监听View 有keypress change click select等用户操作
消息发布订阅模式,View变化 发布一个ui-update,数据变化执行赋值操作发布一个model-update

Observer,能够对数据对象的所有属性进行监听
Compile,对每个元素节点的指令进行扫描和解析
Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图,自身有实例时有update()函数,触发compile中的回调函数
6.vue2对数组、对象数据观察时有什么特殊处理
通过this.$set(object, propertyName, value) 添加响应式property
this.$forceUpdate() 进行局部更新
数组重写了push、pop、shift、unshift、splice、sort、reserve
7.definedProperty和proxy有什么区别
definedProperty 劫持对象的属性,不能监听属性的添加/删除,新元素需要再次definedProperty;修改原来的属性就能触发拦截,触发拦截遍历对象每一个属性
proxy劫持整个代理对象,可以对数组进行下标修改检测、长度检测、支持Map、WeakMap、Set、WeakSet
8.vue数据为什么频繁变化只刷新一次
vue检测到数据变化时,开启一个DOM更新队列,然后在同一事件循环中缓存所有变化数据,如果变化数据多次触发watch,因为watchID相同,只会被推入到队列一次。
9.什么是状态管理,为什么需要状态管理
是将组件之间共享的状态抽取出来,遵循特定的约定统一管理,易于对状态进行追踪和测试,
大量组件通信需要一个存取和操作组件公共状态的地方,
核心思想:统一维护公共的应用状态,通过可控的方式更新状态,状态更新View跟着更新
10.介绍一下vuex或redux
1.vuex
vuex主要用于vue的状态管理,有state mutation action module
state存储数据的地方,view访问this.$store.state.xxx
getter 计算处理state
mutation 修改state唯一地方,同步请求通过commit('xxxmutation')
action view通过,store.dispatch('increment') 提交到action,然后在action 通过store.commit('increment')触发mutation
2.redux
思想规范,单向数据流,函数式FP思想,支持react angular ember
view->actions->reducer->state变化->view
观察者模式、装饰器模式、中间件机制
dispatch(action) 根据actiontype操作stare
11.vuex和redux有什么区别
Redux 通过引入一些中间件解决异步带来的副作用;MobX 没有中间件
Mobx 使用了 Object.defineProperty 拦截 getter 和 setter,用到的数据才会引发绑定,局部精确更新
入口文件 import
from 'mobx-react'
store页面 import { observable, action, } from "mobx";
应用页面 import { inject, observer } from 'mobx-react'
12.如果让你实现一个简单状态管理,要如何实现
设置state公共状态,getter setter dispatch有条件修改store
subscribe 每次dispatch,都进行广播,通知组件store的状态发生了变更
页面中store.getState()获取store数据,store.subscribe(xxx)订阅更新
13.父子组件如何通信
1.props/$emit 父:musics="musicLists" @onEmitIndex="onEmitIndex",子:@click="emitIndex(index) this.$emit('onEmitIndex', index)
2.$parent/$children 父:this.$children[0].messageA = 'this is new value' 子:this.$parent.msg
3.provide/inject 非响应,要实现父子组件响应,父组件传递的数据类型必须是对象Object,子组件接收的数据类型必须是对象Object
14.跨级组件如何通信
1.vuex state、getters、mutations、actions、modules
2.eventBus 初始化空vue实例,EventBus.$emit()发送事件 EventBus.$on()接收事件 EventBus.$off()移除事件
3.localStorage/sessionStorage
通过window.localStorage.setItem(key,value) 存储数据
4.$attrs / $listeners
15.兄弟组件如何通信
eventBus、vuex
16.Virtual DOM是什么
是对真实 DOM 的一种抽象描述,用原生的 JS 对象去描述DOM节点
17.为什么要需要Virtual DOM
为了减少真实DOM操作,减少浏览器重绘重排引起的性能开销
18.Vue的Virtual DOM解决了什么问题
解决DOM更新开销的问题,提升了DOM操作的效率,推动数据驱动式组件开发
19.介绍一下Vue的diff策略
diff整体策略为:深度优先,同层比较
当数据发生改变时,watcher调用patch给真实的DOM打补丁
新旧头尾指针进行比较
20.介绍一下react的diff策略
21.Vue的diff策略和react的diff策略有什么不同
都是忽略跨级比较,只做同级比较,不同在于对同类型节点不同classname处理、及列表对比 vue diff从左右到中间对比,react从左到右依次对比
22.key有什么用
渲染数据识别、dom diff识别,遍历不能用index作为key因为index 是连续的,数据变化会引起重新排列元素顺序
23.computed是如何实现
computed多对一,基于它们的依赖进行缓存,在相关依赖发生改变时它们才会重新求值 computed watch
24.watch如何实现
watch是一个监听动作,一对多(某个值变化引起的业务逻辑)
watch 最终会调用Vue.prototype.watch方法
25.computed引用其他computed 如何实现
computed也是响应式的,内部的get set会跟Object.definedproperty关联起来
computed控制缓存 通过watcher.dirty控制是否读取缓存
computed依赖变化如何更新 computed 会让 【data依赖】 收集到 【依赖computed的watcher】,从而 data 变化时,会同时通知 computed 和 依赖computed的地方
26.介绍一下React Hook
React16.8新增特性,可以在写函数类组件时使用state和React特性,常用有useState useEffect useContext useMemo useCallback useRef
副作用:当函数在运行的过程中对外部环境造成影响,或者与外部环境发生交互,比如操作DOM,发起请求,设置订阅这种,都属于副作用
27.React的Hoc是什么
React状态逻辑复用技术,高阶组件,接收组件作为输入返回组件(一个 React 组件包裹着另外一个 React 组件)
28.vue的mixin是什么
vue提供功能抽象的方法,封装一些可复用的功能,可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的
29.Hoc和mixin有什么区别
都是函数内部再实现一个函数去扩展传入的组件,最后返回一个新的组件,为了更好的复用代码
1.mixin会导致依赖不明确,Mixin 可能会相互依赖,相互耦合
2.mixin会导致命名冲突
3.mixin引入的逻辑和状态是可以相互覆盖的
4.HOC是一个没有副作用的纯函数
5.HOC应用场景 日志打点、权限控制、双向绑定、表单校验
30.为什么Vue没有高阶组件
31.项目如何考虑使用Vue还是React
react灵活的结构和可扩展性,高自由度的编写(几乎无api)可以为手动优化性能带来更大的便利性,社区生态活跃,社区提供了多样性的解决方案和更多的选择
vue易于使用和集成,入门友好,渲染性能更优秀更轻量
React 整体是函数式的思想,数据是单向数据流,需要手动更改达到视图更新
而vue是响应式的进行更改,语法渲染react Fiber 最终考虑项目团队协同,接入成本与学习成本
32.setState是同步还是异步
经过React处理的事件,不会同步更新this.state,可以在setstate回调函数内通过箭头函数拿到更新的state,通过 addEventListener || setTimeout/setInterval 的方式处理的则会同步更新
进入了 react 的调度流程,那就是异步,异步中会把多次更新合并到一次去执行
33.ReactDiff 算法的策略是什么?
1.tree diff React 只对虚拟 DOM 树进行分层比较,不考虑节点的跨层级比较
2.component diff 对于不同类型的组件,默认不需要进行比较操作,直接重新创建,对于同类型组件, 通过让开发人员自定义shouldComponentUpdate()方法来进行比较优化
3.element diff 就是通过唯一 key 来进行 diff 优化,通过复用已有的节点,减少节点的删除和创建操作,同一层级的一组子节点,它们可以通过唯一 key 进行区分
34.React 中 key 的作用是什么?
唯一 key 来进行 diff 优化,通过复用已有的节点,减少节点的删除和创建操作
35.ReactFiber 是什么?为什么要引入?
进程(Process)和线程(Thread),Fiber,英文含义就是“纤维”,比线程(Thread)控制得更精密的并发处理机制
解决JavaScript中同步操作时间过长的方法-分片,React Fiber把更新过程碎片化
36.为什么推荐在 componentDidMount 中发起网络请求?
1.React16.3后将会废弃掉componentWillMount
2.如果在 componentWillMount 里获取数据,fetch data会执行两次,一次在服务端一次在客户端,使用 componentDidMount 则没有这个问题
37.React 代码优化?
1.this绑定处理,定义函数的地方用箭头函数定义,render声明地方用this.xxx()
2.React.lazy(() => import('@material-ui/core/Tooltip'));
3.React.Fragment
38.React 组件设计要掌握哪些原则?
组件是为了更好复用、管理代码,高内聚低耦合,单一职责,接口隔离,代码层面可读性强,复用性高,可维护性好
39.Redux 的核心原理是什么?
1.将应用的状态统一放到state中
2.reducer的作用是返回一个新的state去更新store中对用的state。
3.UI层每一次状态的改变都应通过action去触发,action传入对应的reducer 中
4.可以添加中间件对提交的dispatch进行重写
40.什么是 Redux 中间件?
中间指的是action和store之间,可以让我们改变数据流,实现如异步action ,action过滤,日志输出,异常报告等功能
41.Redux connect 函数的实现策略?
连接React组件与 Redux store ,允许我们将 store 中的数据作为 props 绑定到组件上
在原应用组件上包裹一层,使原来整个应用成为Provider的子组件
42.Mox 的核心原理是什么?
Mobx 最关键的函数在于 autoRun,也叫做依赖收集,Mobx 使用了 Object.defineProperty 拦截 getter 和 setter
43.Redux 和 Mobx 的异同点,如何选择?
React 数据流流动很自然,因为任何 dispatch 都会导致广播,
Mobx 数据流流动不自然,只有用到的数据才会引发绑定,局部精确更新,没有中间件机制,完美支持typescript
前端数据流不太复杂的情况,使用 Mobx,因为更加清晰,也便于维护;
如果前端数据流极度复杂,建议谨慎使用 Redux,通过中间件减缓巨大业务复杂度,但还是要做到对开发人员尽量透明

四、工程化

1.介绍一下webpack的构建流程
entry 找出有哪些模块和库是入口起点(直接和间接)依赖
output 输出路径path和文件名filename,只能指定一个 output
loader 定义在 module.rules,有两个参数:test哪些格式会转换,use转换使用的loader,让webpack 能够去处理其他类型的文件,并将它们转换为webpack 可以处理的有效模块
plugins 转换某些类型的模块,场景:打包优化,资源管理,注入环境变量
mode development\production\none
devServer 配置开发服务器
resolve 路径解析
首先解析参数,找到入口,调用loader转换文件,遍历AST(源代码的抽象语法结构的树) 收集模块依赖码,生成chuank,最后输出文件
2.webpack和rollup、Vite有什么相同和不同
Gulp/Grunt是一种能够优化前端的开发流程的工具
webpack各个模块之间的依赖关系过于复杂 会导致打包速度很慢,使用热更新时,改动一个模块,其他有依赖关系的模块重新打包
Vite koa开启本地服务器,没有webpack那样打包合并的过程,所以启动服务器很快,没被大规模使用,可能隐藏问题
roll up所有代码都在同一个函数作用域里,不支持热更新和代码拆分,将所有小文件生成到一个大文件中,没有其他冗余代码,执行很快
gulp 基于流 基于node,只是对静态资源做流式处理,不支持tree-shaking、热更新、代码分割等
3.常用loader有哪些
vue-loader babel style-loader css-loader url-loader sass-loader ts-loader style-loader
4.介绍一两个Loader的思路
5.常用plugin有哪些,有什么用
htmlWebpackPlugin(打包html文件)
uglifyjsWebpackPlugin(压缩js文件)
webpack-bundle-analyzer: 可视化 Webpack 输出文件的体积 (业务组件、依赖第三方模块)
6.介绍一两个Plugin
7.webpack热更新如何实现
plugin [new webpack.HotModuleReplacementPlugin()]
devServer hot:true
8.webpack层面如何做性能优化
让尽可能少的文件被 Loader 处理
配置resolve 具体安装路径,减少解析耗时
提取公共配置代码
配置DLL 优化第三方库打包
9.介绍一下webpack的dll
优化第三方插件库引用打包问题,
10.介绍一下webpack的tree-shaking
tree-shaking指的就是按需加载,即没有被引用的模块不会被打包进来,减少我们的包大小,缩小应用的加载时间,呈现给用户更佳的体验。
11.介绍一下webpack的scope hosting
使用scope hosting进行配置处理,会将函数作用域进行合并,
plugin new ModuleConcatenationPlugin()
12.介绍一下babel的原理
babel的执行过程就是一个编译转换的工程,转译器transpiler更准确,它只是把同种语言的高版本规则翻译成低版本规则
13.如何实现一个最简模板引擎
构建AST、组合 html、多级作用域以及 实现Filter
14.一个前端页面如何发布到线上
通过CI/CD 与 gitlab集成发布平台,编写或者配置shell,
蓝绿发布 两套环境交替升级,旧版本保留一定时间便于回滚
灰度发布 体验/根据比例发布
滚动发布 构建发布流程,按批次停止老版本实例,启动新版本实例
jenkins Drone
15.cdn
内容分发网络,多种场景内容加速,例如:图片小文件、大文件下载、视音频点播、直播流媒体、全站加速、安全加速。
16.介绍一下weex的原理
移动端跨平台开发
17.为什么weex比H5块
Weex 采用了 Vue 作为上层框架,更加轻量
18.weex有什么缺点
资料少,社区活跃度不够, 成熟的组件少
Weex关于Web标准的实现现在还没有达到100%

五、性能优化

1.webpack打包优化 loader、dll、tree shaking、scope hoisting
2.网络优化 dns cdn 缓存,预加载 ssr
3.代码优化 骨架屏、web worker、虚拟列表、懒加载

六、Typescript

1.介绍一下TypeScript
为 JavaScript 增加了静态类型声明,boolean、number、string、null、void、Array、Object 、any
方法添加类型的最常见的用法是,为参数和返回值添加类型检查
类型别名 :nameObj type nameObj={}
interface 对 user 的类型进行重构
Maybe?String,Maybe可能是String null undefined
Disjoint unions(或操作) type PaymentMethod = Paypal | CreditCard | Bank;
2.Typescript和Javascript相比有什么优势
增加了静态类型声明,代码健壮、写法兼容
3.介绍一下泛型、一般用在什么地方
泛型为了处理不固定的参数,使用泛型后对象或者集合内只能放入指定的数据类型
泛型是一种对类型本身进行抽象的方法
所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔)
每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开
4.介绍一下interface
5.d.ts是什么,d.ts就是TypedDefinition 类型定义文件,用来定义类型信息以及接口规范,js 文件是给运行引擎用的,而 .d.ts 文件是给 IDE(智能编辑器)写代码时参考用的
6.TypeScript是如何编译
7.namespace/module

七、网络

1.常见的状态码有哪些
200 204 301 302 304 403 404 500
2.304表示什么,和302有什么区别
302 临时性重定向,表示资源临时被分配了新的 URL
服务器返回资源前会判断Etag是否与客户端提供的If-None-Match匹配,如果匹配则说明资源未发生改变,此时应返回304
3.介绍一下HTTP缓存策略
浏览器缓存保存着用户通过 HTTP 获取的所有资源,在下一次请求时可以避免重复向服务器发出多余的请求
首先校验本地是否有缓存(强缓存),本地缓存是否过期,然后校验服务器缓存(协商缓存)是否过期
4.connection keep-alive表示什呢
Keep-Alive功能使客户端到服务器端的连接持续有效,服务端在返回 response 后不关闭 TCP 连接
5.介绍一下DNS
DNS(Domain Name System,域名系统) 将域名解析成ip地址
第1步,查找浏览器缓存;第2步,查找系统缓存;第3步,查找路由器缓存。第4步,查找ISP DNS 缓存。
6.三次握手四次挥手
建立客户端和服务端的一条连接,采用三次握手建立一个连接,4次挥手来关闭一个连接
7.介绍HTTPS工作原理
安全套接层(Secure Sockets Layer,缩写作 SSL)是一种安全协议
HTTPS就是使用SSL/TLS协议进行加密传输,让客户端拿到服务器的公钥,然后客户端随机生成一个对称加密的秘钥,使用公钥加密,传输给服务端,后续的所有信息都通过该对称秘钥进行加密解密,完成整个HTTPS的流程。
8.HTTP和HTTPS有什么区别
更小的传输体积,更小或者省略重复的头消息
9.介绍一下CDN应用场景
将内容分布到最接近用户的网络边缘,用以提供用户访问的响应速度。
静态资源、脚本、样式、图片获取
10.从URL到页面展示,发什么了什么
1.浏览器进程检查url 2.检查本地缓存是否缓存了该请求资源 3.进行DNS解析 4.利用ip地址和服务器建立tcp连接 5.构建请求报文 6.服务端处理请求 响应请求 7.客户端接受请求,处理报文 渲染资源
11.HTTP2
HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码
HTTP 消息被送出之后,你就很难中断它了,HTTP2能在不中断 TCP 连接的情况下停止(重置)数据的发送
HTTP2 主动推送
多路复用很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输
HTTP/2完全兼容HTTP/1,是“更安全的HTTP、更快的HTTPS",头部压缩、多路复用等技术
12.GET和POST
GET 还是 POST,用的都是同一个传输层协议
GET用于获取信息,可缓存
POST 用于修改服务器上的数据,不可缓存
GET参数放在URL,POST放在请求体,不会分包处理,本身没有长度限制,分包/限制是浏览器和特定框架的行为
13.常见报文字段
分请求首部、响应首部、实体首部
请求和响应通用常用首部:Cache-Control、Connection、Date、Via
请求首部常见:Accept、Accept-Encoding、Accept-language、Cookie、User-Agent
响应首部常见:Server、Etag、Set-cookie
实体头部常见:Content-Type、Content-language、Content-Encoding、Etag、Last-modify

八、设计模式

1.介绍一下了解的设计模式和应用场景
2.Vue/React中有应用什么设计模式
创建型、结构型、行为型
工厂模式 jQuery的选择器$,创建实例的时候,就可以想想能否用工厂模式实现了
单例模式 熟知的Vuex 和 redux 中的 store
Vue 的 Watch生命周期钩子等等,这些都是观察者模式
装饰器 装饰者模式的作用就是为对象动态的加入某些行为

九、数据结构和算法

1.介绍一下栈/队列/链表
2.用Javascript实现栈/队列/链表
3.树
4.常见排序算法和复杂度
5.动态规划
6.diff

十、安全

验证码,用户体验虽然不好,,但是很多场合下可以防范大多数攻击
token加密解密,这种是目前很常用的手段了,

十一、Node

1.构建Node.js知识体系
NodeJS是基于chrome浏览器的V8引擎构建的,它是单线程单进程模式,不用考虑锁和线程池的问题
2.浏览器和Node的事件循环有和区别
浏览器通常由以下常驻线程组成:1.GUI 渲染线程 2.JavaScript 引擎线程 3.定时触发器线程 4.事件触发线程 5.异步 http 请求线程
Node.js 采用 V8 作为 js 的解析引擎,libuv 是一个基于事件驱动的跨平台抽象层
Node.js 的运行机制如下:
V8 引擎解析 JavaScript 脚本,然后调用API,Libuv将任务分给不同线程
异步队列执行时机不同,在 Node.js 中,microtask 会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行 microtask 队列的任务。浏览器先执行同步再异步
3.聊聊Node.js RPC
4.Understanding Strams in Node.js
5.如何理解Node.js进程与线程
6.请你实现一个大文件上传和断点续传
利用 Blob.prototype.slice 方法,和数组的 slice 方法相似,调用的 slice 方法可以返回原文件的某个切片

大文件上传
前端上传大文件时使用 Blob.prototype.slice 将文件切片,并发上传多个切片,最后发送一个合并的请求通知服务端合并切片
服务端接收切片并存储,收到合并请求后使用流将切片合并到最终文件
原生 XMLHttpRequest 的 upload.onprogress 对切片上传进度的监听
使用 Vue 计算属性根据每个切片的进度算出整个文件的上传进度

断点续传
使用 spark-md5 根据文件内容算出文件 hash
通过 hash 可以判断服务端是否已经上传该文件,从而直接提示用户上传成功(秒传)
通过 XMLHttpRequest 的 abort 方法暂停切片的上传
上传前服务端返回已经上传的切片名,前端跳过这些切片的上传

十二、其他

1.浏览器渲染原理
浏览器工作流程:构建DOM -> 构建CSSOM -> 构建渲染树 -> 布局 -> 绘制。
2.如何独立解决跨域问题
JSONP 利用script标签可跨域的特点,在跨域脚本中可以直接回调当前脚本的函数
CORS 和后端同事配合,服务器设置HTTP响应头中Access-Control-Allow-Origin值,解除跨域限制
iframe 第三方引入
nginx 开发环境配置proxy

3.Serverless中前端开发模式
在传统开发流程中,我们需要前端工程师写页面,后端工程师写接口。后端写完接口之后,把接口部署了,再进行前后端联调。联调完毕后再测试、上线。上线之后,还需要运维工程师对系统进行维护。整个过程涉及多个不同角色,链路较长,沟通协调也是一个问题。
Serverless,后端变得非常简单了,以往的后端应用被拆分为一个个函数,只需要写完函数并部署到 Serverless 服务即可,后续也不用关心任何服务器的运维操作。
不管是Node中间件代理还是nginx反向代理,主要是通过同源策略对服务器不加限制
日常工作中,用得比较多的跨域方案是cors和nginx反向代理
4.节流防抖使用场景
函数防抖和函数节流都是防止某一时间频繁触发
函数防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。 函数防抖就是法师发技能的时候要读条,技能读条没完再按技能就会重新读条。

function debounce(fun, delay) {
    return function (args) {
        let that = this
        let _args = args
        clearTimeout(fun.id)
        fun.id = setTimeout(function () {
            fun.call(that, _args)
        }, delay)
    }
}

规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效
函数节流是间隔时间执行

  function throttle(fun, delay) {
        let last, deferTimer
        return function (args) {
            let that = this
            let _args = arguments
            let now = +new Date()
            if (last && now < last + delay) {
                clearTimeout(deferTimer)
                deferTimer = setTimeout(function () {
                    last = now
                    fun.apply(that, _args)
                }, delay)
            }else {
                last = now
                fun.apply(that,_args)
            }
        }
    }

5.Object.create的基本实现原理
将传入的对象作为原型
6.你了解node多进程吗
child_process.fork 开启多个进程(Node.js 在 v0.8 版本之后新增了Cluster 来实现多进程架构),注意:开启多进程不是为了解决高并发,主要是解决了单进程模式下 Node.js CPU 利用率不足的情况,充分利用多核 CPU 的性能。
7.Node.js 通过提供 cluster、child_process API 创建子进程的方式来赋予8.Node.js “多线程”能力
9.node进程中怎么通信
通过on('message') 监听 send()发送
10.node可以开启多线程吗
child_process fork spawn exec execFile
fork()方法来创建子进程,fork()方法只需要指定要执行的javascript文件模块,即可创建Node的子进程

11.react怎么优化 遍历子节点的时候,不要用 index 作为组件的 key 进行传入
12.实现36进制转换
13.树的遍历有几种方式,实现下层次遍历
深度遍历 广度遍历
14.判断对称二叉树
15.两个有序链表和并成一个有序链表
16.https与http有什么区别(一面刚好也被问到)
HTTP相对于 HTTPS来说,速度较快且开销较小(没有 SSL/TLS) 对接,默认是80端口;
HTTP容易遭受域名劫持,而HTTPS相对来说就较为安全(加密),默认端口为443。
HTTP是明文跑在 TCP 上.而HTTPS跑在SSL/TLS应用层之下,TCP上的
CA(数字签名):
这个是为了防止中间人给偷换了造成数据被窃取而诞生的
用一些权威机构颁布的算法来签名,权威机构做中间人,通讯过程都会跟机构核对一遍
HTTP2压缩数据(HEADER)
多路复用
优先级(可以给请求设置优先级)
17.cookie有哪些属性
Name、Value、Domain、Path、Expires/Max-age、Size
cookie,session,localstorage,sessionstorage有什么区别
session存储在服务端4k,localstorage在本地持久存在,sessionstorage浏览器存在期间遵循同作用域,大小现在在5M以内
node中cluster是怎样开启多进程的,并且一个端口可以被多个进程监听吗
cluster 实现了对 child_process 的封装,通过 fork 方法创建子进程的方式实现了多进程模型
18.怎么禁止js访问cookie
cookie中设置HttpOnly属性
19.options请求方法有什么用
PTIONS它用于获取当前URL所支持的方法
const data = {};
const input = document.getElementById('input');
Object.defineProperty(data, 'text', {
set(value)

});
input.onchange = function(e)

20.如何理解MVVM原理
是一种数据驱动的设计思想,model 代表数据模型,定义数据的操作和修改,view将模型转换成ui展现出来,做的是数据绑定、事件绑定、指令声明,viewmodel是同步model和view的对象。
21.响应式原理是什么
核心原理是数据劫持,数据代理、数据编译、发布订阅
22.Vue如何检测数组变化
使用了函数劫持的方式,重写了数组的方法,Vue将data中的数组进行了原型链重写,指向了自己定义的数组原型方法
23.为何vue采用异步渲染
如果不采取异步更新,那么每次更新数据都会对当前组件进行重新渲染,为了性能考虑,Vue 会在本轮数据更新后,再去异步更新数据。
24.nextTick实现原理
下次 DOM 更新循环结束之后执行延迟回调。nextTick主要使用了宏任务和微任务。根据执行环境分别尝试采用
25.Vue组件的生命周期
beforeCreate是new Vue()之后触发的第一个钩子,在当前阶段data、methods、computed以及watch上的数据和方法都不能被访问。
created 在实例创建完成后发生,当前阶段已经完成了数据观测,也就是可以使用数据,更改数据,在这里更改数据不会触发updated函数。可以做一些初始数据的获取,在当前阶段无法与Dom进行交互,如果非要想,可以通过vm.$nextTick来访问Dom。
beforeMount发生在挂载之前,在这之前template模板已导入渲染函数编译。
mounted在挂载完成后发生,在当前阶段,真实的Dom挂载完毕,数据完成双向绑定,可以访问到Dom节点,使用$refs属性对Dom进行操作。
beforeUpdate发生在响应式数据发生更新,虚拟dom重新渲染之前被触发
updated发生在更新完成之后,当前阶段组件Dom已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新。
beforeDestroy 清除计时器
destroyed 发生在实例销毁之后,这个时候只剩下了dom空壳。组件已被拆解,数据绑定被卸除,监听被移出,子实例也统统被销毁。
26.Ajax放在那个生命周期
created 钩子函数中调用异步请求,更快获取到服务端数据,减少页面loading 时间;ssr不支持mounted钩子函数,放在created保持一致性
27.何时需要使用beforeDestory
28.Vue父子组件生命周期调用顺序
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
父beforeUpdate->子beforeUpdate->子updated->父updated
29.Vue中computed的特点
Computed本质是一个具备缓存的watcher,依赖的属性发生变化就会更新视图
30.watch:deep是如何实现
31.Vue事件绑定原理
原生事件绑定是通过addEventListener绑定给真实元素的,组件事件绑定是通过Vue自定义的$on实现的。
32.v-html会导致什么问题
v-html指令最终调用的是innerHTML方法将指令的value插入到对应的元素里,这就是容易造成xss攻击漏洞
不作为模板编译#
scoped样式不能应用#
33.v-if和v-show区别
当条件不成立时,v-if不会渲染DOM元素,v-show操作的是样式(display),切换当前DOM的显示和隐藏。
34.为什么v-if和v-for不能连用
v-for 比 v-if 具有更高的优先级, v-if 将分别重复运行于每个 v-for 循环中
35.v-model实现原理及如何自定义v-model
v-model其实是一个语法糖,它会自动的在元素或者组件上面解析为 :value="" 和 @input=""
<add-price v-model="price"
@click="$emit('input',value + 100 )" props:['value']
36.组件中data为什么是一个函数
为了保证组件不同的实例之间data不冲突,data必须是一个函数
37.Vue组件如何通信
38.什么是作用域插槽
插槽就是子组件中的提供给父组件使用的一个占位符,用表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签:父组件引用子组件的内部标签使用<template #header> 子:


作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。
<template #header="slotProps"> 子:
{}

39.用vnode描述一个dom结构
40.diff算法的时间复杂度
41.Vue中diff算法原理
Vue2的核心Diff算法采用了双指针两端比较的算法
Vue3在创建VNode时就确定其类型,以及在mount/patch的过程中采用位运算来判断一个VNode的类型,还运用了动态规划的思想求解最长递归子序列。
42.v-for为什么要用key
各个组件 key的作用主要是为了高效的更新虚拟DOM
.key主要用来做dom diff算法用的,diff算法是同级比较
43.描述组件渲染和更新过程
组件初次渲染时解析模板为render函数,触发响应式getter setter,执行render函数生成vnode,更新时修改data,重新执行render函数,生成newVnode
44.Vue模板编译原理
首先解析模版,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。 使用大量的正则表达式对模板进行解析,遇到标签、文本的时候都会执行对应的钩子进行相关处理。
深度遍历AST树,将优化后的AST树转换为可执行的代码
45.Vue常见性能优化
模块按需加载,组件keep-alive进行缓存,图片懒加载,长列表滚动到可视区域动态加载,常用动画进行防抖、节流,key值保持唯一
服务端做ssr
打包优化Tree Shaking/Scope Hoisting
使用cdn加载第三方模块
46.Vue中相同逻辑如何抽离
mixins 来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项
47.为什么要使用异步组件
体量很大的页面时,如果我们不设置加载的优先级的话,那么页面在加载视屏等信息的时候会非常占用时间,然后阻塞后面主要信息的加载
48.谈谈你对keep-alive的了解
keep-alive可以实现组件缓存,当组件切换时不会对当前组件进行卸载,常用的两个属性include/exclude,允许组件有条件的进行缓存。
keep-alive的缓存是基于VNode节点,将需要缓存的VNode节点保存在this.cache中/在render时,如果VNode的name符合在缓存条件(可以用include以及exclude控制),则会从this.cache中取出之前缓存的VNode实例进行渲染
49.实现hash 和history路由
location.hash的值实际就是URL中#后面的东西,每次hash值发生改变的时候,会触发hashchange事件。因此我们可以通过监听该事件,来知道hash值发生了哪些变化,并且不会刷新页面,将会滚动到hash所连接的位置,通过a标签,设置href属性或者通过js直接赋值给location.hash
history路由是用浏览器提供的API实现,window对象中提供了onpopstate事件来监听历史栈的改变,history提供了两个操作历史栈的API: history.pushState 和 history.replaceState
50.Vue-router中导航守卫有哪些
全局路由钩子:beforeEach(to,from, next)、beforeResolve(to,from, next)、afterEach(to,from);
组件内路由钩子:beforeRouteEnter(to,from, next)、beforeRouteUpdate(to,from, next)、beforeRouteLeave(to,from, next)
51.action和mutation的区别
52.简述vuex工作原理
53.Vue3你知道哪些改进
54.ssr
SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端。
SR有着更好的SEO、并且首屏加载速度更快等优点
需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求
55.客户端渲染,服务端渲染,预渲染--区别/详解
CSR:减小服务器压力,首次加载慢要下载js/css等资源容易白屏,加载之后页面响应速度快,可对各种组件进行复用、懒加载;应用场景:管理类的项目。
SSR:部署Nodejs 服务端执行JS,输出HTML给浏览器,开发成本高,需要维护客户端与Node的服务端;适用场景强交互、注重SEO的页面。
Prerendering:通过 Webpack 插件将一些特定页面组件 build 时就编译为 html 文件,直接以静态资源的形式输出给搜索引擎。预渲染的构建是由打包工具在打包的时候就渲染出来了,

0

评论区