2023web前端常考必考面试题及答案汇

1.JS的原型与原型链

每一个对象实例都有自己对应的构造器,对应的构造器都拥有一个prototype的属性,值为一个plainobject,这就是构造器的原型,而且对象实例的proto属性也指向构造器的原型:

a.__proto__===A.prototype

所以构造器原型上的属性方法是可以被对象实例访问到。

因为每一个构造器是prototype原型都是一个对象,理论上来说,这个原型对象也可能是另一个构造器的实例,这样就形成了一条原型的链,在原型链上的实例对象,是可以访问到上级原型对象上的属性方法,原型链的顶层是Object

2.跨域和同源策略

所谓的同源策略其实是浏览器的一种机制,只允许在同源,也就是同协议、同域名、同端口的的情况下才能进行数据交互。

但是我们在开发项目的过程中,往往一个项目的接口不止一个域,所以往往就需要做跨域的处理,通常的跨域方式有这么几种:

1、JSONP,主要依赖的是script标签不受同源策略影响,src指向某一个接口的地址,同步需要传递callback回调函数名字,这样当接口调用成功后,本地创建的全局回调函数就会执行,并且接收到数据。不使用img标签的原因是因为img标签无法执行js语句

2、CORS,依赖服务端对前端的请求头信息进行放行,不做限制。

3、代理访问,前端访问不存在跨域问题的代理服务器,代理服务器再去访问目标服务器(服务器之间没有跨域限制)

3.Redux解决了什么问题?是如何工作的

React框架这样的纯视图的框架对组件通信、状态共享等方面没有太好的解决方案,只能利用状态提升、context之类的技术方案来解决,但是当组件结构、数据流向都比较复杂的时候,React本身的Api解决这样的问题就有些吃力。

此时就可以使用Flux、Redux这样的架构方式来解决问题。

我们之前的项目就在使用Redux,后来又有了rtk,让dux在act组件中的使用更加方便,在一些小型的项目,或者一些小模块中,利用useReducerHook来进行state与dispatch的构建,也能快速优雅的解决问题。

之前的原生Redux中,真实项目开发中,往往需要搭配dux-thunk来进行异步action处理,以及act-dux来进行组件与sto的连接,如果不使用act-dux的话,会比较繁琐。

dux的结构分为sto、Views、Actions、Reducer。

Sto中存储的状态在视图中可以通过getState来获取,也可以通过subscribe方法进行监听,当视图产生UI操作的时候,可以调用actions的方法来生成action后,利用dispatch方法进行派发,此时ducer就会被调用,并且接收到当前的状态与action对象,经过计算出,返回新状态,Sto就会进行状态的更新。

利用act-dux后,组件可以通过connect搭配mapStateToProps及mapDispatchToProps参数来获取sto中的状态及actions中的方法。

使用RTK之后,创建ducer更近方便,利用useSelector和useDispatch可以更快更高效取用状态及派发action。

对于一个小的场景,比如之前我做的注册模块有三个步骤,每个步骤都需要用到第一步用户填写的手机号等信息,这样就形成了几个小组件间的状态共享,如果使用父组件状态提升会导致数据流向不清晰,也犯不上使用dux-sto进行存储,于是就是使用useReducer快速的创建了一个小的sto,内部集成了state与dispatch,搭配Context,也能很高效的解决问题。

4.dux-thunk中间件

这个是解决dux架构中actions方法无法异步返回action的问题的,比如我们在做登录、获取用户信息、获取全局定位城市、获取全局配置等等场景,都是要调用接口异步获取的,此时就可以利用dux-thunk来解决。

thunk中间件的原理其实就是对dispatch进行改写,使其不仅可以接受action对象,也可以接收一个函数,并且会将dispatch动作及getState方法传入到此函数中,我们就可以在这个函数中进行异步动作,异步执行完成后,再去dispatch对应的action。

5.说说你了解的Immutable

Immutable是解决Mutable数据操作中的一些问题的,因为JS数据分为引用类型与基础类型,引用类型在赋值传递的时候往往其实是地址传递,可能会出现一些预料外问题。

Immutable的思想就是构建持久化、不可变的、结构共享的状态,当对immutable数据进行操作的时候,实质上不会更改原数据,而是会根据原数据生成一个新的immutable数据,这样就可以避免刚才说的问题,并且immutable采用的是结构共享的方式,生成新的immutable数据的时候不会完全重建,而是只重新更改后的节点及其父节点,其他节点与上次的immutable数据共享,节省了新建的性能开支。

优点:出问题的概率小,更稳定,比起深拷贝来说性能也更高

缺点:需要重新学习Api,学习成本高,也需要额外导入对应的文件,增加打包体积

其实immutable数据在dux中非常适合,不必再考虑ducer中每次都需要新建新状态的问题,而RTK中已经内部使用了immutable来构建状态。

6.dux是如何通知act数据变更,说通知的过程

dux中sto中的状态需要利用getState方法来获取,在组件中更新的场景只有属性和状态变化才能引起组件的-nder,所以在正常开发中,往往需要将sto中的状态对应的挂载到组件自身的state上,等到sto中状态变化的时候同时更新组件自己的状态,这样就能引起组件的重新渲染最新的数据。

这个时候就需要利用sto,.subscribe方法来监听sto中状态的变化,当sto中状态变化,组件再去更新自己的状态。

利用act-dux的connect之后,就不要写这样的代码了,因为connect根据mapStateToProps生成的容器组件已经去监听状态变化,UI组件只需要在属性上等待接收即可。

7.React中key的作用

React组件在更新的时候,act就会生成新的完整的虚拟DOM树与之前的虚拟dom进行比对,然后再对有更新的节点相关的位置进行更新。

对比之前往往需要进行匹配和比对,为了匹配的更精准,act希望在列表循环等位置去手动为Element添加key属性,这样对比的时候就可以通过查找key来进行精准匹配。

我之前做项目的时候也碰到过这样的情况,一般都是用数据的id来作为key,有一次出现了问题,后端给的数据里头没有id这样的主键·,顺手用了索引做key,在数据列表的顶部添加item的时候对比出错了,最后还是找后端添加唯一id才处理好。

8.说说setState

setState是act类组件更新自身状态的唯一方法,因为act作为纯视图框架,不像vue那样对数据都进行了数据劫持绑定在实例上,当数据更新的时候组件实例对应的watcher会执行,从而引起后续-nder的过程。act只能主动调用setState方法来通知组件进行状态的更新以后虚拟dom的更新、对比、-nder。

setState可以传入一个state对象,采用的是批量更新的方式,并且多个setState会合并,提高更新性能,setState也可以传入一个函数,接收到当前的状态返回出要批量更新的state对象。

setState一般情况下是异步的,也就是说,执行setState之后,不会马上进行nder,并且this.state上的状态也不会马上更新,会等到下一次事件循环中才会去执行。

setState在一些act-api外的方法中可能会是同步的,比如setTimeout、原生dom事件中。

最近的18+版本已经修复了这个问题,所有情况下都是异步的

9.在业务中,初始数据的获取用在那些生命周期方法中

初始数据的获取肯定要在初始化阶段的生命周期钩子函数中执行。

constructor理论上可以执行,因为初始数据的获取往往都是异步的动作。

staticgetDerivedStateFromProps,不可以,因为这是一个静态方法,内部没有this,不适合做这个事儿,nder要保证纯净,不能做这个事情,也可能会导致死循环




转载请注明:http://www.aierlanlan.com/tzrz/7758.html