前言
不出去体会一下就想不到所谓的别人口中的 “大环境不太好” 的具体情况
结果就是:相比上一次确实难多了,之前没投几家最后就确定了,这次真的是达到了海投的地步 (还是准备不够充分,实力不过关)
- 在招企业远没有之前多
- 开放的hc远没有之前的多
- 各种已读不回,回了没下文
- 面试周期长,层层筛选
下面就贴一下自己记录下来的问题,不全面,有的问题简单的写了答案,有的没写,根据自身情况去总结就行
题目
1、useMemo和react.memo区别
● react.memo 是 高阶组件;useMemo 是 hooks;
● react.memo 是 子组件本身是否渲染,可以进行粗粒度的性能优化;useMemo 是 一段函数逻辑是否重复执行,可以进行更加细粒度的性能优化;
2、useReduce和useState
3、如何中断Promose的链式调用
在then方法中返回一个pending状态的promise即可中断
4、interface和type的区别
5、ts中泛型、record、omit
泛型指的是在定义函数/接口/类型时,不预先指定具体的类型,而是在使用的时候在指定类型限制的一种特性。
6、Object.create()
7、自定义hooks
8、react-route的跳转浏览器局部刷新的原理
https://blog.csdn.net/weixin_34550722/article/details/112334139
基于 H5 history 路由:
改变 url 可以通过 history.pushState 和 resplaceState 等,会 将 URL 压入堆栈,同时能够应用 history.go() 等 API 监听 url 的变化可以通过自定义事件触发实现,通过维护的列表,在每次 URL 发生变化的回收,通过配置的 路由路径,匹配到对应的 Component,并且 render
9、loader和plugin的区别及实现
https://blog.csdn.net/qq_35430000/article/details/113919959
10、forwardRef
11、不使用border如何实现边框
12、flex: 0 1 auto
13、align-items和align-content
14、css禁止选中 user-select: none ;
15、css 2D、3D转换
16、简单请求和复杂请求
https://segmentfault.com/a/1190000039891108?utm_source=sf-similar-article
17、为什么要分微任务和宏任务?
https://blog.csdn.net/qq_41732961/article/details/117675693
微任务:Object.observe(已废弃),MutationObserver(html5新特性)
18、为什么hooks不能放到条件和循环里面去
因为 Hooks 的设计是基于数组实现。在调用时按顺序加入数组中,如果使用循环、 条件或嵌套函数很有可能导致数组取值错位,执行错误的 Hook。当 然,实质上 React 的源码里不是数组,是链表
19、babel
babel的转移过程分为三个阶段,这三个步骤分别是:
1、解析parse:将代码解析生成抽象语法树(AST),即词法分析和语法分析的过程。
2、转换Transform:对于AST进行变换的一些列的操作,babel接收得到的AST并通过babel-traverse对其进行遍历,在此过程中进行添加,更新以及移除等操作。
3、生成Generate:将变换后的AST再转换为JS代码,使用到的模块是babel-generator。
20、react合成事件,挂在到document,如何在捕获阶段做操作
21、react hooks闭包陷阱
闭包陷阱产生的原因就是 useEffect 等 hook 里用到了某个 state,但是没有加到 deps 数组里,这样导致 state 变了却没有执行新传入的函数,依然引用的之前的 state。
● 将state添加到依赖项里面去
● 使用全局变量
● useRef
22、compontDidmount和useEffect的区别
23、useLayoutEffect和useEffect
24、react性能优化
- 虚拟列表
- 懒渲染
○ 判断组件是否出现在可视区域内借助react-visibility-observer依赖 - 懒加载
- 列表项使用 key 属性
- 利用缓存
○ 使用 useMemo 和 useCallback 来生成稳定值,并结合 PureComponent 或 React.memo 避免子组件重新 Render - 精确重新计算的范围
○ 给子组件传props的时候一定只传其需要的而并非一股脑全部传入
○ 实现优先级更新,将耗时任务移动到下一个宏任务中执行,优先响应用户行为。
25、css列表、多选框、单选框默认样式
● 列表:list-style
● appearance属性设置none,除该标签的默认样式,保留其原有功能
26、调用 setState 之后发生了什么
在代码中调用setState函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个UI界面。在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。
27、Filber
在 React 15 版本的时候,我们如果有组件需要更新的话,那么就会递归向下遍历整个虚拟 DOM 树来判断需要更新的地方。这种递归的方式弊端在于无法中断,必须更新完所有组件才会停止。这样的弊端会造成如果我们需要更新一些庞大的组件,那么在更新的过程中可能就会长时间阻塞主线程,从而造成用户的交互、动画的更新等等都不能及时响应。
React 的组件更新过程简而言之就是在持续调用函数的一个过程,这样的一个过程会形成一个虚拟的调用栈。假如我们控制这个调用栈的执行,把整个更新任务拆解开来,尽可能地将更新任务放到浏览器空闲的时候去执行,那么就能解决以上的问题。
那么现在是时候介绍 Fiber 了。Fiber 重新实现了 React 的核心算法,带来了杀手锏增量更新功能。它有能力将整个更新任务拆分为一个个小的任务,并且能控制这些任务的执行。
这些功能主要是通过两个核心的技术来实现的:
● 新的数据结构 fiber
● 调度器
Fiber 和 fiber 不是同一个概念。前者代表新的调和器,后者代表 fiber node,也可以认为是改进后的虚拟 DOM。
● fiber
我们可以把每个 fiber 认为是一个工作单元,执行更新任务的整个流程(不包括渲染)就是在反复寻找工作单元并运行它们,这样的方式就实现了拆分任务的功能。
拆分成工作单元的目的就是为了让我们能控制 stack frame(调用栈中的内容),可以随时随地去执行它们。由此使得我们在每运行一个工作单元后都可以按情况继续执行或者中断工作(中断的决定权在于调度算法)。
fiber 内部其实存储了很多上下文信息,我们可以把它认为是改进版的虚拟 DOM,它同样也对应了组件实例及 DOM 元素。同时 fiber 也会组成 fiber tree,但是它的结构不再是一个树形,而是一个链表的结构。
总的来说,我们可以认为 fiber 就是一个工作单元的数据结构表现,当然它同样也是调用栈中的一个重要组成部分。
● 调度器简介
每次有新的更新任务发生的时候,调度器都会按照策略给这些任务分配一个优先级。比如说动画的更新优先级会高点,离屏元素的更新优先级会低点。
通过这个优先级我们可以获取一个该更新任务必须执行的截止时间,优先级越高那么截止时间就越近,反之亦然。这个截止时间是用来判断该任务是否已经过期,如果过期的话就会马上执行该任务。
然后调度器通过实现 requestIdleCallback 函数来做到在浏览器空闲的时候去执行这些更新任务。
这其中的实现原理略微复杂。简单来说,就是通过定时器的方式,来获取每一帧的结束时间。得到每一帧的结束时间以后我们就能判断当下距离结束时间的一个差值。
如果还未到结束时间,那么也就意味着我可以继续执行更新任务;如果已经过了结束时间,那么就意味着当前帧已经没有时间给我执行任务了,必须把执行权交还给浏览器,也就是打断任务的执行。
另外当开始执行更新任务(也就是寻找工作单元并执行的过程)时,如果有新的更新任务进来,那么调度器就会按照两者的优先级大小来进行决策。如果新的任务优先级小,那么当然继续当下的任务;如果新的任务优先级大,那么会打断任务并开始新的任务。
28、安全相关
- XSS 跨站脚本攻击,一种代码注入攻击
○ 输入过滤,对input输入框进行输入限制,防止输入一些特殊符号,按照规定的格式输入
○ httpOnly:在cookie中设置HttpOnly属性后,js脚本将无法读取到cookie信息
○ 转义HTML:如果拼接 HTML 是必要的,就需要对于引号,尖括号,斜杠进行转义,但这还不是很完善.想对 HTML 模板各处插入点进行充分的转义,就需要采用合适的转义库 - CSRF 跨站请求伪造
○ 同源检测,服务器检测请求来源;
○ 使用 token 来进行验证;
○ 验证码,强制用户与应用交互,体验较差 - 本质上讲,XSS 是代码注入问题,CSRF 是 HTTP 问题。 XSS 是内容没有过滤导致浏览器将攻击者的输入当代码执行。CSRF 则是因为浏览器在发送 HTTP 请求时候自动带上 cookie,而一般网站的 session 都存在 cookie里面(Token验证可以避免)。
29、react-dom
30、react 中的 render方法
31、http、https,http1.0,1.1,2.0
32、webpack版本区别
33、微前端原理
● 微前端解决了什么问题
https://blog.csdn.net/qq_41694291/article/details/113842872
34、websocket重连
35、Map的缺点
36、为什么区分宏任务微任务
为了插队。
37、react生命周期
38、vue和react组 件通信的区别
react组件通信
- propps/回调函数
- createContext/useContext
- 状态管理库
- events库跨组件通信(需要npm安装)
39、类组件的优点
40、类组件和函数组件区别
- 语法上
○ 函数组件是一个纯函数,它接收一个props对象返回一个react元素。而类组件需要去继承React.Component并且创建render函数返回react元素,这将会要更多的代码 - 状态和生命周期钩子
○ 函数式组件没有这些,但加入了hooks之后,可以实现这些
41、vue和react的区别
相同点
- 组件化
- 数据驱动视图
- 都有虚拟dom
不同点
- 语法
○ 模板语法、指令 vs JSX - diff算法不同
○ vue对比节点时,当节点元素类型相同,类名不同时,认为是不同的元素,删除重新创建,而react认为是同类型的节点,进行修改属性操作
○ vue列表对比的时候,采用从两端到中间的方式,旧集合和新集合两端各存在两个指针,两两进行比较,每次对比结束后,指针向队列中间移动;react则是从左往右一次对比,利用元素的index和lastindex进行比较
○ 当一个集合把最后一个节点移动到最前面,react会把前面的节点依次向后移动,而Vue只会把最后一个节点放在最前面,这样的操作来看,Vue的diff性能是高于react的 - 状态
○ vue直接修改,react只能通过setState去修改
42、引用数据类型为什么放在对内存
引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。
地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。
43、session和cookie区别
cookie保存在浏览器端,session保存在服务端。
存储内容不同:cookie只能存储字符串,而session存储结构类似于hashtable的结构,可以存放任何类型。
存储大小:``cookie最多可以存放4k大小的内容,session则没有限制。
session的安全性要高于cooKie
44、css权重
行级>id>class|伪类|属性>标签
45、定位
static 认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
sticky 粘性定位
inherit 规定从父级继承定位
46、hooks实现原理
https://zhuanlan.zhihu.com/p/443264124
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性,讨论下添加hook的动机:
● 组件之间服用状态逻辑很难
● 复杂组件变的难以理解
● class难以理解
47、addEventListener和onclick的区别
.onclick是会被同时注册的onclick覆盖的,onclick后面的事件会覆盖前面的事件
.addEventListener则不会被覆盖,会按事件的先后顺序执行。
48、浏览器内核原理
由渲染引擎和js引擎(谷歌v8引擎)组成
https://juejin.cn/post/6844903569200513037
49、react ssr原理
整体来说 react 服务端渲染原理不复杂,其中最核心的内容就是同构。
node server 接收客户端请求,得到当前的req url path,然后在已有的路由表内查找到对应的组件,拿到需要请求的数据,将数据作为 props、context或者store 形式传入组件,然后基于 react 内置的服务端渲染api renderToString() or renderToNodeStream() 把组件渲染为 html字符串或者 stream 流, 在把最终的 html 进行输出前需要将数据注入到浏览器端(注水),server 输出(response)后浏览器端可以得到数据(脱水),浏览器开始进行渲染和节点对比,然后执行组件的componentDidMount 完成组件内事件绑定和一些交互,浏览器重用了服务端输出的 html 节点,整个流程结束。
https://blog.51cto.com/u_15283585/2954378
50、双飞翼布局
- flex布局, 中间的设置flex:1
- 中间用padding撑开,两边定位
51、箭头函数和普通函数
- this
- 语法
- 箭头函数没有arguments
- 箭头函数没有原型,所以不能new
- 箭头函数可以省略大括号隐式返回
52、爬楼梯算法
// 1 1
// 2 11 2
// 3 111 12 21
// 4 1111 211 121 112 22
// 5 11111 122 212 221 1112 1121 1211 211
// 找规律 前两次之和
const fn = n => {
if(!n || n < 1) return new Error('参数错误!')
let first = 1
let second = 2
let result
if(n === 1) return 1
if(n === 2) return 2
for(let i = 3; i <= n; i++){
result = first + second
first = second
second = result
}
return result
}
53、hooks有什么缺点
不能出现在条件,循环,嵌套中
可能出现闭包陷阱的问题
54、useState为什么返回一个数组而不是对象
降低使用的复杂度
数组按顺序解构,对象不按顺序,必须和对象的的属性同名,多次声明得设置别名
55、async/await异常捕获
56、金额格式化
57、react项目的优化点
● include 或 exclude 限制 loader 范围。
● happypack多进程编译
● 缓存babel编译过的文件
● tree Shaking 删除冗余代码
● 按需加载,按需引入
● shouldComponentUpdate ,PureComponent 和 React.memo, useMemo, useCallback调优
● 循环中加入key
● 路由懒加载
● 合理使用状态管理
● 海量数据优化-时间分片,虚拟列表
58、闭包的使用场景
59、jwt
60、redux中间件
61、设计模式
62、原型链的终点, 为什么
63、跨端技术方案
64、git add和git commit
65、常见的的loader和 plugin
66、https加密算法
● 对称加密,常见对称加密算法DES,AES
● 非对称加密,常见非对称加密算法RSA,DSA
● 数字证书和数字签名
● 单向加密算法
67、如何阻止事件冒泡和捕获
1、event.stopPropagation() 阻止冒泡
2、preventDefault 阻止冒泡并且阻止浏览器的默认行为
3、return false 之后的所有触发事件和动作都不会被执行. 有时候 return false 可以用来替代stopPropagation() 和
preventDefault()
68、类组件如何绑定this,为什么要绑定this
1、箭头函数不需要绑定
● 箭头函数内没有this,默认用父级作用域的this。
● 当应用new关键字时,this指向新对象,同时箭头函数中的this也被赋值为了新对象且永远不会更改指向。
普通函数需要绑定
69、offsetwidth和clientwidth
clientWidth = width+左右padding
offsetWidth = width + 左右padding + 左右boder
scrollWidth:获取指定标签内容层的真实宽度(可视区域宽度+被隐藏区域宽度)。
70、使用useMemo和useCallback有什么缺陷
useCallback、useMemo是做缓存并优化性能,但是缓存机制也是有开销的,使用方法不正确会导致负优化
https://www.jianshu.com/p/9769075ecbfe
71、前端工程化理解
前端工程可以定义为,将工程方法系统化地应用到前端开发中,以系统、严谨、可量化的方法开发、运营、维护前端应用程序
前端工程也经历了类似的过程:
● B/S 架构兴起,进而有了前端、后端之分
● 随着前端复杂度的上升,模块复用、实践规范越来越重要
● 为了管理和简化前端开发过程,前端框架、自动化、构建系统应运而生并发展迅猛
● 基于行业最佳实践,开箱即用的框架(如dva)、工具体系等逐渐建立起来
前端越来越重,复杂度越来越高,配套的前端工程体系也在不断发展和完善,可简单分为开发、构建、发布 3 条主线,三大主线撑起了前端工程体系,系统地覆盖了前端开发的主流程
https://blog.csdn.net/sd19871122/article/details/123182083
72、react搭配各个状态管理的使用场景,优劣
● redux 函数式编程思想
优点
1、流程规范,按照官方推荐的规范和结合团队风格打造一套属于自己的流程。
2、函数式编程,在 Reducer 中,接受输入,然后输出,不会有副作用发生,幂等性。
3、可追踪性,很容易追踪产生 BUG 的原因。
缺点
1、流畅太繁琐,需要写各种 Action,Reducer。
2、要想完成异步数据,得配合其他库。
● mobx 面向对象,响应式编程思想
优点
1、学习成本少,基础知识非常简单,跟 Vue 一样的核心原理,响应式编程。
2、写更少的代码,完成更多的事。不会跟 Redux 一样写非常多的样板代码。
3、使组件更加颗粒化拆分。
缺点
1、过于自由,MobX 提供的约定及模版代码很少,如果团队不做一些约定,容易导致团队代码风格不统一。
2、可拓展,可维护性,也许你会担心 Mobx 能不能适应后期项目发展壮大呢?确实 Mobx 更适合用在中小型项目中,但这并不表示其不能支撑大型项目,关键在于大型项目通常需要特别注意可拓展性,可维护性,相比而言,规范的 Redux 更有优势,而 Mobx 更自由,需要我们自己制定一些规则来确保项目后期拓展,维护难易程度;
73、vue和react设计思想的区别及选型
1.设计思想不同
react 的设计思想是:函数式的思想,把组件设计成纯函数,状态和逻辑通过参数传入,通过单向数据流保证状态的统一化。 react 希望数据是不可变的。所以,结合 immutable 来实现数据不可变。 immutable 是一种持久化的数据,一旦被创建就不会被修改。如果修改了 immutable 对象,也是返回了一个新的 immutable, 但是原数据不变。
vue 的设计思想是:响应式的思想,也是基于数据是可变的,通过监听器 watcher 监听每一个属性的变化,实现虚拟 dom 的更新。 react的性能优化需要手动去做,而vue的性能优化是自动的。
当 state 特别多的时候,vue 的 watcher 响应也会使应用卡顿。而 react 不会有这个问题,这就是为什么 react 更适合大型的应用服务
2.模板处理方式不同
react 是 all - in -js, html css js 都统一到一个 js 文件中,所以,react 实现一个jsx模板引擎来处理文件
vue 是 html css js 分开的通过 template style script 来统一到一个 .vue 文件中
选型
● 应用需要尽可能的小和快就用vue,vue渲染速度比react快
● 大型项目建议用react,因为vue模板的使用不容易发现错误、也不易拆分和测试
● 如果要适用于web和原生app的项目,就使用react native
74、react16前后对比
75、react为什么要自定义事件流
● 进行浏览器兼容,实现更好的跨平台。React 采用的是顶层事件代理机制,能够保证冒泡一致性,可以跨浏览器执行。React 提供的合成事件用来抹平不同浏览器事件对象之间的差异,将不同平台事件模拟合成事件。
● 避免垃圾回收。事件对象可能会被频繁创建和回收,因此 React 引入事件池,在事件池中获取或释放事件对象。即 React 事件对象不会被释放掉,而是存放进一个数组中,当事件触发,就从这个数组中弹出,避免频繁地去创建和销毁(垃圾回收)。
● 方便事件统一管理和事务机制
76、项目中乾坤如何做样式隔离
● 人为用css前缀来隔离开主应用和子应用
● css in js的库,styled-components
● 配置 webpack 修改 less 变量
77、虚拟dom的优缺点
https://blog.csdn.net/m0_68309348/article/details/124408997
78、如何预防中间人攻击
● https
● 不要在公共Wi-Fi网络上购买或发送敏感数据
● 确保浏览的网站没有任何混合内容
● 不要忽略浏览器的警告,不要点击恶意链接或电子邮件
● 不要下载盗版内容
79、DNS 解析会出错吗,为什么
● 网络不可用
● 域名劫持
● 没有注册的网站会出现DNS解析错误;
● 域名是否被禁用解析
80、es6中 set的内部实现
81、模块化发展历程
https://blog.csdn.net/qq_36131788/article/details/114383417
82、TCP 有哪些手段保证可靠交付
● 确认应答:ACK和序列号
● 超时重传:发送数据包在一定的时间周期内没有收到相应的ACK,等待一定的时间,超时之后就认为这个数据包丢失,就会重新发送
● 流量控制:控制发送方发送窗口的大小来实现流量控制
● 拥塞控制:控制传输上流量
83、no-cache 和 no-store 的区别
no-store:不在客户端做缓存,一直去服务端请求资源
no-cache:每次去服务端验证资源新鲜度,也就是走协商缓存
84、grid布局和flex区别是什么?
flex:一维布局
grid:二维布局,网格布局
84、flex布局: 一行显示固定个数,换行展示
85、react diff 比对
15版本
React用三大策略 将O(n3)复杂度 转化为O(n)复杂度
(1)策略一(tree diff):忽略节点跨层级操作场景,提升比对效率。
(2)策略二(component diff):如果组件的 class 一致,则默认为相似的树结构,否则默认为不同的树结构。这也就是为什么shouldComponentUpdate、PureComponent 及 React.memo 可以提高性能的原因。
(3)策略三(element diff):同一层级的子节点,可以通过标记 key 的方式进行列表对比。
86、Mutation Observer构造函数
Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个API 都可以得到通知,
87、树形数据查找某一条数据
88、css定位属性如何继承
position:inherit 规定元素从父级继承定位
89、为列表元素,原生写法
90、图片不知宽高情况下,如何做自适应
91、闭包缓存的状态外部可以修改吗
92、react中事件立即执行
93、link和@import区别
link属于html标签,而@import是css提供的。
页面被加载时,link会同时被加载,而@import引用的css会等到页面被加载完再加载的。
兼容性问题:@import只在IE5以上才能识别,而link是html标签,无兼容性问题。
权重问题:@import的权重要高于link。
DOM操作:DOM可以操作link中的样式,而不可以操作@import中的样式。
94、window.onload和document.ready的区别
window.onload不能同时编写几个,如果同时包含几个,则只能运行一个,而另外一个可以同时编写多个,而且都可以执行。
window.onload指示页面包含图片等文件在内的所有元素都加载完成之后开始执行
document.ready表示文档结构已经加载完成(不包含图片等非文字媒体文件)之后开始执行
95、href和scr的区别
● href表示指向网络资源的所在位置,用来建立和当前元素或当前文档之间的联系。
● src会将其指向的资源下载并应用到文档中,比如 js 脚本,img 图片,frame;当浏览器解析到带有src属性的这些元素的时候,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕
96、react为啥不能直接修改state
- 性能问题
React提倡不可变性,通过setstate()修改state实际上是创建了一个副本用来代替原来的state,这与直接修改原数据有着本质的区别。其他框架类似angular监听一个变量的变化通过watch和deepwatch,尤其deepwatch在判断一个数据量大的变量是否变化时会消耗很多资源,导致应用性能下降。而在React中则是数据变化就产生新对象将之替代,没变化就直接返回原数据,通过判断新旧变量的引用是否一致来判断变量是否修改,这样做的效率要比前者高的多。 - 机制
要知道setState本质是通过一个队列机制实现state更新的。 执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。
如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。
97、setState和useState参数
- setState
○ 第一个参数可以是对象也可以是函数,第二个参数是回调函数,可选
○ 如果状态的变化基于上次的state,第一个参数就使用方法,这个方法的接收值就是就是上次的state
○ 第二个函数的参数就是当前状态更新之后的值 - useState
○ 可以接收一个对象或者一个方法
○ 如果状态的变化基于上次的state,第一个参数就使用方法,这个方法的接收值就是就是上次的state
97、css3 2D、3D
transform+translate : 平移
transform+rotate: 旋转
transition : 定义过度动画
98、webpack热更新(hmr)
https://sunlianglife.yuque.com/br84d8/hh39na/bi6v90
1.第一步,在 webpack 的 watch 模式下,文件系统中某一个文件发生修改,webpack 监听到文件变化,根据配置文件对模块重新编译打包,并将打包后的代码通过简单的 JavaScript 对象保存在内存中。
2.第二步是 webpack-dev-server 和 webpack 之间的接口交互,而在这一步,主要是 dev-server 的中间件 webpack-dev-middleware 和 webpack 之间的交互,webpack-dev-middleware 调用 webpack 暴露的 API对代码变化进行监控,并且告诉 webpack,将代码打包到内存中。
3.第三步是 webpack-dev-server 对文件变化的一个监控,这一步不同于第一步,并不是监控代码变化重新打包。当我们在配置文件中配置了devServer.watchContentBase 为 true 的时候,Server 会监听这些配置文件夹中静态文件的变化,变化后会通知浏览器端对应用进行 live reload。注意,这儿是浏览器刷新,和 HMR 是两个概念。
4.第四步也是 webpack-dev-server 代码的工作,该步骤主要是通过 sockjs(webpack-dev-server 的依赖)在浏览器端和服务端之间建立一个 websocket 长连接,将 webpack 编译打包的各个阶段的状态信息告知浏览器端,同时也包括第三步中 Server 监听静态文件变化的信息。浏览器端根据这些 socket 消息进行不同的操作。当然服务端传递的最主要信息还是新模块的 hash 值,后面的步骤根据这一 hash 值来进行模块热替换。
5.webpack-dev-server/client 端并不能够请求更新的代码,也不会执行热更模块操作,而把这些工作又交回给了 webpack,webpack/hot/dev-server 的工作就是根据 webpack-dev-server/client 传给它的信息以及 dev-server 的配置决定是刷新浏览器呢还是进行模块热更新。当然如果仅仅是刷新浏览器,也就没有后面那些步骤了。
6.HotModuleReplacement.runtime 是客户端 HMR 的中枢,它接收到上一步传递给他的新模块的 hash 值,它通过 JsonpMainTemplate.runtime 向 server 端发送 Ajax 请求,服务端返回一个 json,该 json 包含了所有要更新的模块的 hash 值,获取到更新列表后,该模块再次通过 jsonp 请求,获取到最新的模块代码。这就是上图中 7、8、9 步骤。
7.而第 10 步是决定 HMR 成功与否的关键步骤,在该步骤中,HotModulePlugin 将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用。
8.最后一步,当 HMR 失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新打包代码。
99、盒子模型
● ie盒模型:宽高包括border和padding, box-sizing: border-box
● 标准盒模型: box-sizing : context-box
100、splice和slice
slice (截取)
● 返回截取的元素数组,不会修改原数组
● 只有两个参数,两个参数都表示数组下标,可以接受负数,截取的数组不包含第二个参数下标对象的数据
splice (删除并添加)
● 返回删除的元素数组,会修改原数组
● 第一个参数表示起始位置下标(不包含此下标本身),第二个参数表示要删除的数量,后面的参数表示要添加的数据
101、0.1+0.2底层
102、bigint缺点
兼容性
103、filber更新过程,如何重启和中断
104、首屏加载慢有哪些优化手段
● 静态资源压缩,懒加载
● 路由懒加载
● 按需加载
● cdn加速
● 网络、缓存方面
● 减少重复请求
105、react17,18
106、weakMap,weakSet
107、随机数
Math.floor(): 返回数字的下舍整数
Math.random():返回随机数,默认0-1之间
● 0-10:Math.floor(Math.random() * 10)
● 1-10:Math.floor(Math.random() * 10 + 1 )
● 5 - 100:Math.floor(Math.random() * 100 + 5)
108、高阶组件适用场景
● 代码复用抽象逻辑
● 利用高阶组件的条件渲染特性可以对页面进行权限控制, 权限控制一般分为两个维度:页面级别和页面元素级别。
● 页面复用
109、配css需要哪些loader
● css-loader
● style-loader
110、取数组最大值(es5,es6)
// es5
Math.max.apply(null, [22,33,11])
// es6
Math.max(...[22,33,44])
// reduce 取最大
[14,3,77,30].reduce((accumulator, currentValue)=>{
return accumulator = accumulator > currentValue ? accumulator : currentValue
});
// sort排序取最大
111、some、every、find、filter、map、forEach有什么区别
112、给一万个button添加点击事件
利用世界委托将事件添加到父级元素上通过判断通过判断事件对象的target内容来判断是按钮触发还是其他地方触发
● e.target.tagName可以判断标签
113、js继承优缺点
https://blog.csdn.net/yyysss9/article/details/125593460
114、前端项目性能优化
115、做过哪些webpack配置,tree shanking怎么做的
116、mobx内部状态变化监听怎么实现的
基于响应式原理Object.defineProperty