前端面试题

前端面试题

1. 说说你对react的理解?有哪些特性?

理解

React,用于构建用户界面的 JavaScript 库,提供了 UI 层面的解决方案
遵循组件设计模式、声明式编程范式和函数式编程概念,以使前端应用程序更高效
使用虚拟DOM来有效地操作DOM,遵循从高阶组件到低阶组件的单向数据流

特性

JSX语法
单向数据绑定
虚拟DOM
声明式编程
Component

特点

声明式设计
组件化
高效
灵活
Jsx语法

2. 说说Real diff算法是怎么运作的?

理解

跟Vue一致,React通过引入Virtual DOM的概念,极大地避免无效的Dom操作,使我们的页面的构建效率提到了极大的提升
而diff算法就是更高效地通过对比新旧Virtual DOM来找出真正的Dom变化之处
原理

react中diff算法主要遵循三个层级的策略:

tree层级
conponent 层级
element 层级

tree层级

DOM节点跨层级的操作不做优化,只会对相同层级的节点进行比较
只有删除、创建操作,没有移动操作

conponent层级

如果是同一个类的组件,则会继续往下diff运算,如果不是一个类的组件,那么直接删除这个组件下的所有子节点,创建新的

element层级

对于比较同一层级的节点们,每个节点在对应的层级用唯一的key作为标识
提供了 3 种节点操作,分别为 INSERT_MARKUP(插入)、MOVE_EXISTING (移动)和 REMOVE_NODE (删除)
通过key可以准确地发现新旧集合中的节点都是相同的节点,因此无需进行节点删除和创建,只需要将旧集合中节点的位置进行移动,更新为新集合中节点的位置

3. 说说React生命周期有哪些不同的阶段?每个阶段对应的方法是?

初始化阶段:

由ReactDOM.render()触发-----初次渲染
1.	constructor()
2.	componentWillMount()
3.	render()		必须的
4.	componentDidMount()   常用,一般在这个钩子做一些初始化,如:开启定时器、发送网络请求、订阅消息

更新阶段:

由组件内部this.setState()或父组件render触发
1.	shouldComponentUpdate()
2.	componentWillUpdate()
		forceUpdate()强制更新用得少
3.	render()		必须的
4.	componentDidUpdate()   

卸载阶段:

componentWillUnmount()	常用,一般在这个钩子做一些收尾的事情,如:关闭定时器、取消订阅消息

其他生命周期

componentWillReceiveProps:父组件与子组件进行数据传递时触发
getDerivedStateFromProps: static getDerivedStateFromProps(nextProps, prevState),这是个静态方法,当我们接收到新的属性想去修改state,可以使用getDerivedStateFromProps,衍生新的state,此方法在更新个挂载阶段都可能会调用
getSnapshotBeforeUpdate: getSnapshotBeforeUpdate(prevProps, prevState),这个方法在render之后,componentDidUpdate之前调用,有两个参数prevProps和prevState,表示之前的属性和之前的state,这个函数有一个返回值,会作为第三个参数传给componentDidUpdate,如果你不想要返回值,可以返回null,此生命周期必须与componentDidUpdate搭配使用

4. 说说你对React中虚拟dom的理解?

理解

实际上它只是一层对真实DOM的抽象,以JavaScript 对象 (VNode 节点) 作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作使这棵树映射到真实环境上
创建虚拟DOM就是为了更好将虚拟的节点渲染到页面视图中,所以虚拟DOM对象的节点与真实DOM的属性一一照应

实现原理

React虚拟DOM的实现原理,通过JS模拟网页文档节点,生成JS对象树(虚拟DOM),然后再进一步生成真实的DOM树,再绘制到屏幕。如果后面有内容发生改变,React会重新生成一棵全新的虚拟DOM树,再与前面的虚拟DOM树进行比对diff,把差异的部分打包成patch,再应用到真实DOM,然后渲染到屏幕浏览器。

5. 说说你对react hook的理解?

Hook是React16.8的新增特性。它可以让你在不编写class的情况下用state以及其他的React特性
他用于react的函数组件中
Hooks中包含:useState,useEffect,useCallback,useMemo,useRef,useReducer等
hooks的出现,使函数组件的功能得到了扩充,拥有了类组件相似的功能,在我们日常使用中,使用hooks能够解决大多数问题,并且还拥有代码复用机制,因此优先考虑hooks

6. React组件之间如何通信?

父传子:⽗组件可以通过向⼦组件传 props 的⽅式来实现
子传父:可以采用props+回调的方式
兄弟组件通信:可以通过兄弟节点的共同父节点,由父节点转发信息,实现兄弟间通信
跨层级通信:context状态树
发布者订阅者模式:发布者发布事件,订阅者监听到事件后做出反应,可以通过引⼊ event 模块进⾏
全局状态管理工具:可以借助 Redux 或 Mobx以及react-redux 等全局状态管理⼯具进⾏通信,它们会维护⼀个全局状态中⼼(Store),并可以根据不同的事件产⽣新的状态
hooks中帮我们封装好的:useContext和useReducer

7. 说说你对受控组件和非受控组件的理解?应用场景?

受控组件

就是受我们控制的组件,组件的状态全程响应外部数据
我们在输入框输入内容的时候,会发现输入的内容并无法显示出来,也就是input标签是一个可读的状态
如果想要解除被控制,可以为input标签设置onChange事件,输入的时候触发事件函数,在函数内部实现state的更新,从而导致input框的内容页发现改变
受控组件我们一般需要初始状态和一个状态更新事件函数

非受控组件

就是不受我们控制的组件
一般情况是在初始化的时候接受外部数据,然后自己在内部存储其自身状态

应用场景

大部分时候推荐使用受控组件来实现表单,因为在受控组件中,表单数据由React组件负责处理
如果选择非受控组件的话,控制能力较弱,表单数据就由DOM本身处理,但更加方便快捷,代码量少

8. 说说Connect组件的原理是什么?

Connect是一个高阶组件
高阶组件就是一个函数,传给它一个组件,它返回一个新的组件。
这个函数本身是可以传参的,可以映射store的属性,
Connect接受四个参数,他的作用就是连接react组件与redux可以让我们将store的数据作为props绑定到组件上

9. 说说react 中jsx语法糖的本质?

Jsx是语法糖,实质是js函数,需要babel来解析,核心函数是React.createElement(tag,{attrbuties},children),参数tag是标签名可以是html标签和组件名,attrbuties参数是标签的属性,children参数是tag的子元素。用来创建一个vnode,最后渲染到页面上

10. 说说你对redux中间件的理解?常用的中间件有哪些?实现原理?

理解

中间件(Middleware)是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的
类似于插件,可以在不影响原本功能、并且不改动原本代码的基础上,对其功能进行增强。在Redux中,中间件主要用于增强dispatch函数。
Redux中,中间件就是放在就是在dispatch过程,在分发action进行拦截处理

常用的中间件

redux-thunk:通过action返回一个函数进行异步操作
redux-promise :通过action返回一个promise进行异步处理
redux-logger:用于日志记录

实现原理

中间件本身是一个函数,该函数接收一个store参数,表示创建的仓库,该仓库并非一个完整的仓库对象,仅包含getState,dispatch。该函数运行的时间,是在仓库创建之后运行。
由于创建仓库后需要自动运行设置的中间件函数,因此,需要在创建仓库时,告诉仓库有哪些中间件
需要调用applyMiddleware函数,将函数的返回结果作为createStore的第二或第三个参数。
中间件函数必须返回一个dispatch创建函数

11. 说说AMD、CMD、commonJS模块化规范的区别?

这三个规范都是为Js模块化加载而生的,使模块能够按需加载,使系统同庞杂的代码得到组织和管理。模块化的管理代码使多人开发得到了更好的合作

commonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作
AMD规范是非同步加载模块,允许指定回调函数
CMD规范是延期执行模块

12. 说说package.json中版本号的规则?

第一部分为主版本号,变化了表示有了一个不兼容上个版本的大更改
第二部分为次版本号,变化了表示增加了新功能,并且可以向后兼容
第三部分为修订版本号,变化了表示 有bug修复,并且可以向后兼容
第四部分为日期版本号加希腊字母版本号,希腊字母版本号共有五种,分别为base、alpha、 bela 、RCrelease

13. 说说React jsx转换成真实DOM的过程?

使用react.createElement或者JSX编写react组件,实际上所有的JSX代码都会转换成react.createElement内容,babel帮助我们完成了转换的过程,createElement函数对key和ref等特殊的props进行了处理,并获取defaultProps对默认的props进行赋值,并且对传入的子节点进行处理,最终构造成一个dom对象

14. 说说你对@reduxjs/toolkit的理解?和react-redux有什么区别?

@reduxjs/toolkit

一个开箱既用的高效redux开发工具,旨在成为标准的readux逻辑开发模式

react-redux

将所有的组件分为了两大类,ui组件以及容器组件,其中容器组件包含着ui组件,容器组件负责和redux进行交互

15. React render方法的原理,在什么时候会触发?

在类组件和函数组件中,render函数的形式是不同的。
在类组件中render函数指的就是render方法;而在函数组件中,指的就是整个函数组件。
render的执行时机主要分成了两部分:

类组件调用 setState 修改状态:
函数组件通过useState hook修改状态

16. React性能优化的手段有哪些?

1、使用纯组件;(PureComponent) 
2、使用 React.memo 进行组件记忆(React.memo 是一个高阶组件),对 于相同的输入,不重复执行;
3、如果是类组件,使用 shouldComponentUpdate(这是在重新渲染组件之前触发的其中一个生命周期事件)生命周期事件,可以利用此事件来决定何时需要重新渲染组件;
4、路由懒加载;
5、使用 React Fragments 避免额外标记;
6、不要使用内联函数定义(如果我们使用内联函数,则每次调用“render”函数时都会创建一个新的函数实例);
7、避免在Willxxx系列的生命周期中进行异步请求,操作dom等;
8、如果是类组件,事件函数在Constructor中绑定bind改变this指向;
9、避免使用内联样式属性;
10、优化 React 中的条件渲染;
11、不要在 render 方法中导出数据;
12、列表渲染的时候加key;
13、在函数组件中使用useCallback和useMemo来进行组件优化,依赖没有变化的话,不重复执行;
14、类组件中使用immutable对象;

17. 如何通过原生js实现一个节流函数和防抖函数?

本质上是优化高频率执行代码的一种手段

防抖

当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间(非常短的时间);
当事件密集触发时,函数的触发会被频繁的推迟;
只有等待了一段时间也没有事件触发,才会真正的执行响应函数;

应用场景:
	输入框中频繁的输入内容,搜索或者提交信息;
	频繁的点击按钮,触发某个事件;
	监听浏览器滚动事件,完成某些特定操作;
	用户缩放浏览器的resize事件;

节流

当事件触发时,会执行这个事件的响应函数;
如果这个事件会被频繁触发,那么节流函数会按照一定的频率来执行函;
不管在这个中间有多少次触发这个事件,执行函数的频繁总是固的;

应用场景:
	游戏中的一些设计--王者荣耀 英雄的普攻; 
	监听页面的滚动事件;
	鼠标移动事件; 				
	用户频繁点击按钮操作;

18. 说说你对koa中洋葱模型的理解?

Koa是一个精简的node框架,被认为是第二代Node框架,其最大的特点就是独特的中间件流程控制,是一个典型的洋葱模型,它的核心工作包括下面两个方面:

1.	将node原生的req和res封装成为一个context对象。
2.	基于async/await的中间件洋葱模型机制。

什么是洋葱模型

Koa的洋葱模型是以next()函数为分割点,先由外到内执行Request的逻辑,然后再由内到外执行Response的逻辑,这里的request的逻辑,我们可以理解为是next之前的内容,response的逻辑是next函数之后的内容,也可以说每一个中间件都有两次处理时机。洋葱模型的核心原理主要是借助compose方法。

为什么需要洋葱模型

因为很多时候,在一个app里面有很多中间件,有些中间件需要依赖其他中间件的结果,用葱模型可以保证执行顺序,如果没有洋葱模型,执行顺序可能出乎我们的预期

19. 说说如何借助webpack来优化前端性能?

随着前端的项目逐渐扩大,必然会带来的一个问题就是性能
尤其在大型复杂的项目中,前端业务可能因为一个小小的数据依赖,导致整个页面卡顿甚至奔溃
一般项目在完成后,会通过webpack进行打包,利用webpack对前端项目性能优化是一个十分重要的环节
通过webpack优化前端的手段有:

•	JS代码压缩
•	CSS代码压缩
•	Html文件代码压缩
•	文件大小压缩
•	图片压缩
•	Tree Shaking,Tree Shaking 是一个术语,在计算机中表示消除死代码
•	代码分离
•	内联 chunk

关于webpack对前端性能的优化,可以通过文件体积大小入手,其次还可通过分包的形式、减少http请求次数等方式,实现对前端性能的优化

20. 说说你对webSocket的理解?

WebSocket是一种基于TCP的全双工通信协议,在应用层。

为什么需要WebSocket

1、传统上的HTTP协议它是无状态的,服务器不能够识别是哪个客户端发送的请求,不能够保存状态。
2、WebSocket弥补了这一问题,在客户端向服务端发送请求之后,服务器处理请求并返回到客户端,使用WebSocket可以使得服务器主动向浏览器推送消息

WebSocket协议的原理

与服务器进行三次握手,建立TCP连接 向服务器发送HTTP请求,请求中包含WebSocket的版本信息:包括upgrade、connection等等。 服务器处理请求并返回客户端,此时可以进行WebSocket请求了 服务端也可以主动向客户端推送消息了。

WebSocket的优缺点

优点:建立WebSocket连接之后,客户端与服务端交流更方便
客户端只需要向服务端发送一次请求,服务端主动向客户端发送消息
缺点:在服务端的状态不会频繁变化的时候,就不需要使用WebSocket连接了,浪费性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值