前端面试题总结(二)

前端面试题总结

1、说说对React的理解?有哪些特性?

1、React是用于构建用户界面的JavaScript库,只提供了UI层面的解决方案,遵循组件设计模式、声明式编程范式和函数式编程概念,使得前端应用程序更加高效。
2、使用虚拟DOM来有效地操作DOM,遵循从高阶组件到低阶组件的单向数据流,帮助我们将界面成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,构成整体页面。
3、特性:JSX语法、单项数据绑定、虚拟DOM、声明式编程、Component

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

1、diff算法是为了节省性能而设计的,通过同层级进行比较,不跨层级使得性能更加高效
2、运作流程主要分为三层:tree层、component层、element层
1、tree层:tree层对于DOM节点的跨层级移动的操作忽略,只对相同层级的DOM节点进行比较,一旦发现节点不存在,直接删除该节点以及以下的所有子节点
2、component层:遇到同一个类型的组件遵循tree
diff,进行层级对比,遇到不同类型的组件,直接将这个不同的组件判断为脏组件,并且替换该组件之下的所有的子节点,当知道这个组件的虚拟DOM没有任何变化,就可以手动使用,shouldComponentUpdate来判断是否需要进行diff,进一步提升了diff效率和性能
3、element层:低于同一层级,面对全新节点,可以实现插入的操作;面对多余的节点,执行删除操作;面对换位的节点,执行移动的操作

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

1、React生命周期主要分为三个阶段:创建阶段、更新阶段和卸载阶段
2、创建阶段:
1、constructor:用来定义状态,或者是用来存放一些this的方法;
2、getDerivedStateFromProps():将来会使用的,需要返回一个新的对象作为新的state或者返回null表示state状态不需要更新
3、render():类组件必须实现的方法,用于渲染DOM结构,可以访问组件state与prop属性
4、componentDidMount():用于执行一些数据获取,事件监听等操作
3、更新阶段:
1、getDerivedStateFromProps():将来会使用的,需要返回一个新的对象作为新的state或者返回null表示state状态不需要更新
2、shouldComponentUpdate:用于告知组件本身基于当前的props和state是否需要重新渲染组件,默认情况返回true
3、render:类组件必须实现的方法,用于渲染DOM结构,可以访问组件state与prop属性
4、getSnapshotBeforeUpdate:该周期函数在render后执行,执行之时DOM元素还没有被更新,目的在于获取组件更新前的一些信息,比如组件的滚动位置之类的,在组件更新后可以根据这些信息恢复一些UI视觉上的状态
5、componentDidUpdate:可以根据前后的props和state的变化做相应的操作,如获取数据,修改DOM样式等
4、卸载阶段:
componentWillUnmount:此方法用于组件卸载前,清理一些注册是监听事件,或者取消订阅的网络请求等,一旦一个组件实例被卸载,其不会被再次挂载,而只可能是被重新创建

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

1、虚拟DOM用js对象的形式,来模拟页面dom的嵌套关系;
2、虚拟DOM是一棵虚拟的JavaScript对象树,画重点,”虚拟的“、”JS对象“,指的是它把真实的网页文档节点,虚拟成一个个的js对象,并以树型结构,保存在内存中。
3、实现原理:通过JS模拟网页文档节点,生成JS对象树(虚拟DOM),然后再进一步生成真实的DOM树,再绘制到屏幕。如果后面有内容发生改变,React会重新生成一棵全新的虚拟DOM树,再与前面的虚拟DOM树进行比对diff,把差异的部分打包成patch,再应用到真实DOM,然后渲染到屏幕浏览器。

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

1、Hook是React 16.8.0版本增加的新特性/新语法,可以让你在函数组件中使用 state 以及其他的 React 特性
常见的Hook:
2、useState:跟类组件中state类似,方便我们定义初始化的数据,接收两个参数,一个是初始化数据,另一个是修改数据的方法
3、useEffect:副作用函数,只有使用之后,才会产生副作用,他接受两个参数,一个是函数,另一个是要监听的数据,可以是[],表示只执行一次,也可以传参,传参之后只要当我们的数据发生变化时才会触发,如果不写,那么发生一次变化就会执行一次
4、useMemo:数据缓存,当我们进行组件通信时,如果我们父组件中的数据发生变化,那么我们的子组件也会随着进行更新,不管我们更新的数据是否跟我们的子组件的数据有关系,他都会进行更新操作,这时候,就会存在更新性能的浪费,我们可以使用ysememo来进行缓存,减少不必要的更新操作,他的缓存的参数是一个字符串,如果是一个函数的话,那么我们的usememo就会失效,这时候就需要使用useCallback进行数据的缓存操作
5、useRef:可以监听我们的输入框数据的变化,获取输入框中的值

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

React组件通信就是值组件通过某种方式来传递信息以达到某个目的
方式:
1、父组件向子组件传递信息:由于react数据流动是单向的,父组件在调用子组件时,只需要在子组件标签内传递参数,子组件通过props属性接收
2、子组件向父组件传递信息;父组件向子组件传递一个函数,然后通过这个函数的回调,拿到子组件传过来的值
3、兄弟组件之间的传递:父组件作为中间层来实现数据的互通,通过使用父组件传递
4、父组件向后代组件传值:使用context提供的组件通信的一种方式,可以实现数据的共享,Provider组件通过value属性传递给后代组件
5、非关系组件传递数据:将数据进行一个全局的资源管理,从而实现组件间的通信功能,例如redux

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

1、受控组件:在React中,可变状态通常保存在组件的状态属性中,并且只能使用 setState()
更新,而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称受控组件。简单说就是收到setState的控制,组件的状态全程响应外部数据
2、非受控组件:表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值(使用
ref从DOM获取表单值),不受setState的控制,一般在初始化的时候接收外部的数据,然后自己在内部存储其自身的状态 应用场景:
1、受控组件:强制输入格式、一个数据的多个输入、动态输入、提交时的验证问题 2、非受控组件:一次性取值(提交时)、提交时的验证

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

1、Connect连接redux和react,包裹在我们容器组件外层,接收上边的Provider提供的store里state和dispatch,传给一个构造函数,返回一个对象,以属性的形式传递给我们的容器组件
2、Connect是一个高阶函数,首先传入mapStateToProps、mapDispatchToProps,然后返回Component函数,然后将真正的Component作为参数传入,从而返回一个新的组件

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

1、Jsx的本质就是函数React.createElement的语法糖,所有的jsx语法都会最终经过babel.js转化为React.createElement这个函数调用
2、三个参数:type是指的当前的元素类型,config是jsx属性,以对象的属性和值的形式存储,children是存放在标签中的内容
3、jsx写法:必须引入babel并且设置script标签的type为text/bable
babel:将jsx转化为React.createElement()这种函数的调用

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

1、Redux中间件就是介于应用系统和系统软件之间的一类软件,使用系统软件提供的基础服务,衔接网络上应用系统的各个部分或者是不同的应用,达到资源共享,功能共享的目的
2、常用的中间件:redux-thunk用于异步操作、redux-logger用于日志的记录

实现原理:所有中间件被放进一个数组中嵌套执行,判断传递过来的数据类型,最后执行store.dispatch,中间件内部middleware
API可以拿到getstate和dispatch方法。

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

1、AMD:这种规范就是异步的加载模块,先定义所有依赖,然后加载完成后的回调函数中执行require([‘xxx’],function(){})
2、CMD:依赖就近原则,用的时候在写 function(require,exports,module){require(‘xxx’)}
3、commonJS:加载模块使用require(‘xxx’) 区别:
1、AMD和CMD最大的区别就是对依赖模块的执行时机处理不同,二者均为异步加载模块
2、AMD依赖前置,js可以方便的知道依赖模块是谁,立即加载,CMD就近依赖,需要把模块变为字符串解析
3、commonJS是所有代码都运行在模块作用域,不会污染全局作用域,模块加载是同步的,只有加载完成后才可以执行后边的操作,requeire的值是被输出的值的拷贝,模块内容变化也不会影响这个值

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

^:只会执不更改左边非零数字的更新 :如果写入的是0.13.0,则当运行npm update时i,会更新到补丁版本

:接收高于指定版本的任何版本
=:接受等于或者高于指定版本的任何版本 <=:接受等于或者低于指定版本的任何版本 <:接受低于指定版本的任何版本
=:接收确切的版本
-:接受一定范围的版本 ||:组合集合 无符号:接收指定的特定版本 Latest:使用可以用的最高版本

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

1、使用React.createElement或jsx编写react组件,实际上所有的jsx代码最后都会转换成React.ccreateElement(…),babel帮助我们完成转换的过程
2、createElement函数对于key和ref等特殊的props进行处理,并获取defaultProps对默认的props进行赋值,并且对传入的子节点进行处理,最终构成一个虚拟DOM对象
3、ReactDOM.render将生成好的虚拟DOM渲染到指定的容器上,其中采用了批处理,事务等机制并且对特定的浏览器进行了性能优化,最终转换为真实DOM

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

1、React-redux是官方react
UI绑定层,允许React组件从redux存储中读取数据,并将操作分派到存储以更新的状态。提供了connect,Provider等API,帮助我们连接react和redux,实现的逻辑会更加的严谨高效
2、@reduxjs/tookit是对Redux的二次封装,开箱即用的一个高效的Redux开发工具,使得创建store,更新store
区别:
1、reduxjs/tookit相对于react-redux来说比较方便,集成了redux-devtools-extension,不需要额外的配置,非常方便
2、reduxjs/tookit集成immutable-js的功能,不需要安装配置使用,提升了开发效率
3、reduxjs/tookit集成了redux-thunk的功能
4、reduxjs/tookit将types、actions、reducers放在一起组成了全新的slices,简化了我们的使用

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

Render函数在react中有两种形式,在类组件中指的是render方法,在函数组件中,指的是函数组件本身,在render中我们会编写jsx,jsx通过babel编译后就会转化为我们熟悉的js格式,在render过程中,React将新调用的render函数返回的树与旧版本的树进行比较,决定如何更新DOM,然后进行diff比较,更新DOM树
触发时机: 1、类组件调用setState修改状态时; 2、函数组件通过useState Hook修改状态时;
3、类组件重新渲染时; 4、函数组件重新渲染时;

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

1、通过shouldComponentUpdate:对比state和props,确定是否重新渲染,默认返回true,不希望渲染返回false
2、PureComponent:通过对比state和props间比较结果来实现
3、React.memo:缓存组件的渲染,避免不必要的更新(只能用于函数组件)
4、避免使用内联函数:每次调用render时就会重新渲染一个新的函数,在组件内部创建一个函数,将事件绑定到该函数本身 5、使用React
Fragments避免额外标记 6、使用Immutable:减少渲染的次数
7、懒加载组件:使用suspense和lazy组件实现代码拆分功能 8、事件绑定方式 9、服务端渲染

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

1、函数节流: 频繁触发,但只在特定的时间内才执行一次代码 2、函数防抖:
频繁触发,但只在特定的时间内没有触发执行条件才执行一次代码
3、区别:两者区别在于函数节流是固定时间做某一件事,比如每隔1秒发一次请求。而函数防抖是在频繁触发后,只执行一次(两者的前提都是频繁触发)
4、节流应用场景:函数节流的应用场景一般是onrize,onscroll等这些频繁触发的函数,比如你想获取滚动条的位置,然后执行下一步动作
5、防抖应用场景:输入框搜索自动补全事件,频繁操作点赞和取消点赞等等,这些应用场景,也可以通过函数节流来实现,频繁操作点赞和取消点赞,因此需要获取最后一次操作结果并发送给服务器

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

1、在koa中,中间件被next()方法分成两部分,next方法上面会先执行,下边部门会在后续中间件执行全部结束后再执行,
2、在洋葱模型中,每一层相当于一个中间件,用来处理特定的功能,比如错误处理,session处理等,其处理顺序先是next()请求,然后执行next()函数,最后是next()响应,也就是说每一个中间件都有两次处理时机。
3、洋葱模型的核心原理是借助componse方法
Koa的洋葱模型是以next()函数为分割点,先由外到内执行Request的逻辑,然后再由内到外执行Response的逻辑,这里的request的逻辑,我们可以理解为是next之前的内容,response的逻辑是next函数之后的内容,也可以说每一个中间件都有两次处理时机。洋葱模型的核心原理主要是借助compose方法

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

1、压缩代码:删除多余的代码、注释、简化代码的写法等等⽅式。可以利⽤webpack的 UglifyJsPlugin 和
ParallelUglifyPlugin 来压缩JS⽂件 2、利⽤ cssnano (css-loader?minimize)来压缩css
3、利⽤CDN加速: 在构建过程中,将引⽤的静态资源路径修改为CDN上对应的路径。可以利⽤webpack对于 output
参数和各loader的 publicPath 参数来修改资源路径 4、Tree Shaking:
将代码中永远不会⾛到的⽚段删除掉。可以通过在启动webpack时追加参数
–optimize-minimize 来实现 5、Code Splitting: 将代码按路由维度或者组件分块(chunk),这样做到按需加载,同时可以充分利⽤浏览器缓存 6、提取公共第三⽅库:
SplitChunksPlugin插件来进⾏公共模块抽取, 7、利⽤浏览器缓存可以⻓期缓存这些⽆需频繁变动的公共代码

20、 说说你对webSocket的理解?

1、理解:webSocket是一种网络传输协议,位于OSI模型的应用层,可在单个TCP连接上进行双工通信,能够更好的节省服务器资源和带宽并达到实时通讯。客户端和服务器只需要完成一次握手,两者之间就可以创建出持久性的连接,并进行双向数据传输
2、特点: 1、全双工(通信允许数据在两个方向上同时传输)
2、二进制帧(采用二进制帧的结构,语法语义与HTTP完全不兼容,更侧重与实时通信)
3、协议名(引入ws和wss分别代表明文和密文的websoket协议,且默认端口使用80或者443,几乎与http完全一致)
4、握手(有一个握手过程然后正式收发数据)

21、bind、call、apply 区别?如何实现一个bind?

Call、bind、apply作用都是改变函数执行时的this指向
区别:
1、apply接收两个参数,第一个参数是this指向,第二个参数是函数接收的参数,以数组的形式传入
2、Call方法的第一个参数也是this指向,后面传入的是一个参数列表
3、Bind方法和call相似,第一个参数也是this指向,后边传入的也是一个参数列表(这个列表可以分多次传入),bind是返回绑定this之后的函数,apply和call是立即执行

//如何实现一个bind:修改this指向,动态的传递参数,兼容new关键字
使用function.prototype.mybind = function(context){
	//判断调用对象是否为函数
	If(typeof this !==function){throw new TypeError(“error”)}
	//获取参数
	Const args = [...arguments].slice(1)
	Fn = this
	Return function Fn(){
//根据调用方式,传入不同的绑定值
	Return fn.apply(this instanceof Fn ? new fn(...arguments):context,args.concat(...arguments))
}
}

22、 什么是防抖和节流?有什么区别?如何实现?

节流:n秒内只允许一次,如果在n秒内重复触发,只有一次生效 防抖:n秒后在执行该事件,如果在n秒内被重复触发,则重新计时 区别:
1、函数防抖在一段连续操作结束以后,处理回调,利用clearTimeout和setTimeout实现;函数的节流,在一段连续操作中,每一段事件只执行一次,频率较高的事件中使用来提高性能
2、函数防抖关注一定时间连续触发的时间,只在最后执行一次,而函数节流一段时间内只执行一次

23、怎么理解回流跟重绘?什么场景下会触发?

回流:布局引擎会根据各种样式计算每个盒子在页面上的位置和大小
重绘:当计算好盒模型的位置、大小以及其他属性后,浏览器根据每个盒子的特性进行重新绘制 触发时机:
回流:添加或删除可见的DOM元素;元素位置发生变化、元素的尺寸发生变化、内容发生变化,比如文本变化或者图片被代替;页面一开始渲染的时候、浏览器的窗口尺寸变化
重绘:触发回流时一定触发重绘,另外还有颜色的修改、文本方向的修改、阴影的修改等

24、VUE路由的原理?

路由分为两种模式:hash模式和history模式 原理:
Hash:url中的hash值是客户端的一种状态,当向服务器端发送请求时,hash部分不会被发送,hash的改变,都会在浏览器的访问历史中增加一个记录,因此我们可以通过浏览器的回退,前进按钮控制hash的切换,通过改变hash值来进行页面的跳转
History:在history的模式下,前端的url必须和实际向后端发起请求的url一致,pushState和replaceState两个API来操作实现url的变化,可以在页面不刷新的情况下,操作浏览器的历史记录,也可以使用popstate来监听url的变化,从而实现页面的跳转功能

25、你了解vue的diff算法吗?说说看?

Diff算法是一种通过同层的树节点进行比较的高效算法,有两个特点:比较只会在同层级中进行比较,变化跨层级进行比较;在diff的比较过程中,循环从两边向中间进行比较
原理:
1、当数据发生变化时,set方法会调用Dep.notify通知所有订阅者watcher,订阅者就会调用patch给真实的DOM打补丁,更新相应的视图
2、每次diff都会调用updateChildren方法来比较,然后层层递归下去,直到将旧Vnode和新Vnode中的所有子节点对比完。domDiff的过程更像是两个树的比较,每找到相同节点时,都会一层层的往下比较它们的子节点,是一个深度递归遍历比较的过程

26、说说你对keep-alive的理解?

1、Keep-alive是vue中的内置组件,能在组件切换的过程中将状态保留在内存中,防止重复渲染DOM,也就是所谓的组件缓存
2、Keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁他们
3、Keep-alive可以设置props属性:include字符串或正则表达式,只有当名称匹配时才会被缓存;
4、exclude:字符串或者正则表达式,任何名称匹配的组件都不会被缓存,max数字,最多可以缓存多少组件实例

27、什么是响应式设计?响应式设计的基本原理是什么?如何做?

响应式网站设计:是一种网络页面设计布局,页面的设计与开发应当根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的响应和调整
响应式设计的基本原理:是通过媒体查询检测不同的设备屏幕尺寸做处理,为了处理移动端,页面头部必须有meta声明viewport 实现方式:
1、媒体查询:设置不同类型的媒体条件,并根据对应的条件,给相应符合条件的媒体调用相对应的样式表
2、百分比:当浏览器的宽度或者高度发生变化时,通过百分比单位,可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果
3、vw/vh:vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度。任意层级元素,在使用vw单位的情况下,1vw都等于视图宽度的百分之一
4、rem:rem是相对于根元素html的font-size属性,默认情况下浏览器字体大小为16px,此时1rem = 16px

28、如何解决跨域问题?

出于浏览器的同源策略限制产生的跨域问题,浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域 解决:
1、jsonp跨域 2、Nginx反向代理 3、Php端修改header
4、Document.domain实现不同window之间的相互访问和操作 5、Cors解决跨域
6、Window.name利用了浏览器的特性来做到不同域之间的数据传递;

29、如何优化webpack打包速度?

1、尽可能的减少模板上使用loader,减少loader被频繁执行的频率
2、跟上开发技术的迭代:node,yarn,npm,webpack保持最新最稳定的版本
3、Plugin尽量少并可靠,选择性能好,官方推荐的插件 4、Resolve参数的合理配置
5、使用DllPlugin提升webpack的打包速度 6、控制包文件的大小
7、Thread-loader、parallel-webpack、happypack多进程打包

30、SPA首屏加载速度慢的怎么解决?

首屏加载:浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容
1、减小入口文件体积:,把不同路由对应的组件分割成不同的代码块,待路由被请求的时候会单独打包路由,使得入口文件变小,加载速度大大增加
2、静态资源本地缓存:采用http缓存设置响应头,采用service worker离线缓存,合理利用localstroage
3、UI框架按需加载 4、组件重复打包 5、图片资源的压缩 6、开启GZip压缩
7、使用SSR:服务端渲染,组件或页面通过服务器生成html字符串,再次发送到浏览器

31、说说react router有几种模式?实现原理?

两种模式:hash模式和history模式 Hash原理:hash 值改变,触发全局 window 对象上的 hashchange
事件。所以 hash 模式路由就是利用 hashchange 事件监听 URL 的变化,从而进行 DOM 操作来模拟页面跳转
History原理:利用了 HTML5 History Interface 中新增的 pushState () 和
replaceState () 方法。

32、从浏览器地址栏输入url到显示页面的步骤?

1、浏览器根据请求的 URL 交给 DNS 域名解析,找到真实 IP,向服务器发起请求;
2、服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图像等) 3、浏览器对加载到的资源(HTML、JS、CSS
等)进行语法解析,建立相对应的内部数据结构(如 HTML 的 DOM); 4、载入解析到的资源文件,渲染页面,完成。

33、说说JavaScript中的数据类型?存储上的差别?

基本类型:number、string、Boolean、undefined、null、symbol
复杂类型:object、array、function 存储的区别: 1、位置不同:基本数据类型存储在栈中,引用类型的对象存储与堆中
2、声明变量时内存地址分配:简单类型的值栈中存放的是对应的值,引用数据类型栈中存放的是指向堆的内存地址
3、简单基本类型赋值是生成相同的值,两个对象对应不同的地址,复杂类型赋值将保存对象的内存地址赋值给另一个变量,两个变量指向堆内存中的同一个对象

34、说说对React Hooks的理解?解决了什么问题?

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React
特性 解决问题: 1、难以重用和共享组件中与状态相关的逻辑 2、由于业务变动,函数组件不得不改为类组件
3、逻辑复杂的组件难以开发和维护,当组件需要处理多个不相关的local state时,每个生命周期函数中肯能会包含各种互不相关的逻辑
4、类组件在基于现有工具的优化上存在的些许问题
5、hooks的出现,使函数组件的功能得到了扩充,拥有了类组件相似的功能,在我们日常使用中,使用hooks能够解决大多数问题,并且还拥有代码复用机制,因此优先考虑hooks

35、说说你对promise的了解?

1、Promise是最早由社区提出和实现的一种解决异步编程的方案,比其他传统的解决方案(回调函数和事件)更合理和更强大。
2、promise是为解决异步处理回调金字塔问题而产生的
3、Promise对象的状态不受外界影响,Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由
pending变成fulfilled或者由pending变成rejected
4、Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由
JavaScript 引擎提供,不用自己部署。resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从
pending 变为
resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从
pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
5、Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

36、 说说webpack中常见的Loader?解决了什么问题?

1、loader 用于对模块的源代码进行转换,在import或加载模块时预处理文件
2、Style-loader:将css添加到DOM的内联样式标签style中
3、Caa-loader:将css文件通过require的方式引入,并且返回css代码 4、Less-loader:处理less
5、Sass-loader:处理sass 6、Postcss-loader:处理postcss来处理css
7、File-loader:分发文件到output目录并返回相对路径 8、Html-minify-loader:压缩html

37、说说 React 性能优化的手段有哪些?

1、通过shouldComponentUpdate:对比state和props,确定是否重新渲染,默认返回true,不希望渲染返回false
2、PureComponent:通过对比state和props间比较结果来实现
3、React.memo:缓存组件的渲染,避免不必要的更新(只能用于函数组件)
4、避免使用内联函数:每次调用render时就会重新渲染一个新的函数,在组件内部创建一个函数,将事件绑定到该函数本身 5、使用React
Fragments避免额外标记 6、使用Immutable:减少渲染的次数
7、懒加载组件:使用suspense和lazy组件实现代码拆分功能 8、事件绑定方式 9、服务端渲染

38、 说说 React中的setState执行机制?

一个组件显示形态就可以由数据状态和外部参数决定,而数据状态就是state,当需要修改值的状态就通过seState来改变,从而达到更新组件内部数据的作用
SetState更新数据时就可以分为同步和异步更新,在组件生命周期或react合成事件中,setState就是异步的,在setTimeout或原生的dom事件中,setState就是同步的

39、 Vue组件之间的通信方式都有哪些?

这类问题 首先分类 表明了解的比较多 具体就没说完 或者漏了 面试官也不会计较很多 组件通信的四大类 父与子 子与父 子与子 跨层级
在细说各种方式 加入自己的理解
1、props和 e m i t 父组件向子组件传递数据是通过 p r o p 传递的,子组件传递数据给父组件是通过 emit父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过 emit父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过emit触发事件
2、 a t t r s 和 attrs和 attrslisteners 3、中央事件总线
bus上面两种方式处理的都是父子组件之间的数据传递,而如果两个组件不是父子关系呢?这种情况下可使用中央事件总线的方式。新建一个Vue事件bus对象,然后通过bus. e m i t 触发事件, b u s . emit触发事件,bus. emit触发事件,bus.on监听触发的事件。
4、provide和inject父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深只要调用了
inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。
5、v-model:父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this. e m i t ( ‘ i n p u t ’ , v a l ) 自动修改 v − m o d e l 绑定的值 6 、 emit(‘input’,val)自动修改v-model绑定的值 6、 emit(input,val)自动修改vmodel绑定的值6parent和$children 说说vue中Key值的作用 说说vue中的虚拟dom和diff算法
7、boradcast和dispatch 8、vuex处理组件之间的数据交互
如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。

40、 说说React生命周期中有哪些坑?如何避免?

1、 getDerivedStateFromProps 容易编写反模式代码,使受控组件和非受控组件区分模糊
2、 componentWillMount 在 React
中已被标记弃用,不推荐使用,主要的原因是因为新的异步架构会导致它被多次调用,所以网络请求以及事件绑定应该放到
componentDidMount 中 3、 componentWillReceiveProps 同样也被标记弃用,被
getDerivedStateFromProps 所取代,主要原因是性能问题。 4、 shouldComponentUpdate 通过返回
true 或者 false 来确定是否需要触发新的渲染。主要用于性能优化。 5、 componentWillUpdate
同样是由于新的异步渲染机制,而被标记废弃,不推荐使用,原先的逻辑可结合 getSnapshotBeforeUpdate 与
componentDidUpdate 改造使用。 6、如果在 componentWillUnmount
函数中忘记解除事件绑定,取消定时器等清理操作,容易引发
bug。如果没有添加错误边界处理,当渲染发生异常时,用户将会看到一个无法操作的白屏,所以一定要添加

41、调和阶段setState干了什么?

1、 代码中调用 setState 函数之后,React
会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。 2、 经过调和过程,React
会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面; 3、 在 React 得到元素树之后,React
会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染; 4、 在差异计算算法中,React
能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。

42、说说redux的实现原理是什么,写出核心代码?

  1. 将应用的状态统一放到state中,由store来管理state。
  2. reducer的作用是返回一个新的state去更新store中对用的state
  3. 按redux的原则,UI层每一次状态的改变都应通过action去触发,action传入对应的reducer 中,reducer返回一个新的state更新store中存放的state,这样就完成了一次状态的更新
  4. subscribe是为store订阅监听函数,这些订阅后的监听函数是在每一次dipatch发起后依次执行
  5. 可以添加中间件对提交的dispatch进行重写

43、 React合成事件的原理?

react中的事件都是合成事件,不是把每一个dom的事件绑定在dom上,而是把事件统一绑定到document中,触发时通过事件冒泡到document进行触发合成事件,因为是合成事件,所以我们无法去使用e.stopPropagation去阻止,而是使用e.preventDefault去阻止。
合成事件:循环所有类型的eventPlugin,对应每个事件类型,生成不同的事件池,如果是空,则生成新的,有则用之前的,根据唯一key获取到指定的回调函数,再返回带有参数的回调函数。

44、 为什么react元素有一个$$type属性?

目的是为了防止 XSS 攻击。 因为 Synbol 无法被序列化,所以 React 可以通过有没有 t y p e o f 属性来断出当前的 e l e m e n t 对象是从数据库来的还是自己生成的。如果没有 typeof 属性来断出当前的 element 对象是从数据库来的还是自己生成的。 如果没有 typeof属性来断出当前的element对象是从数据库来的还是自己生成的。如果没有typeof 这个属性,react 会拒绝处理该元素。

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

Redux中间件就是介于应用系统和系统软件之间的一类软件,使用系统软件提供的基础服务,衔接网络上应用系统的各个部分或者是不同的应用,达到资源共享,功能共享的目的
常用的中间件:redux-thunk用于异步操作、redux-logger用于日志的记录
实现原理:所有中间件被放进一个数组中嵌套执行,判断传递过来的数据类型,最后执行store.dispatch,中间件内部middleware
API可以拿到getstate和dispatch方法。

46、说说你对事件循环event loop的理解?

JavaScript是一门单线程的语言,意味着同一时间内只能做一件事情,但是并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环
所有的任务都分为同步任务、异步任务。 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
异步任务:ajax网络请求、setTimeout定时器函数 同步任务进⼊主线程,即主执⾏栈,异步任务进⼊任务队列,主线程内的任务执
⾏完毕为空,会去任务队列读取对应的任务,推⼊主线程执⾏。那么上述过程的不断重复就称为事件循环。

47、前端跨域的解决方案?

1、 Jsonp跨域:利用script标签没有跨域限制,src属性发送带有callback参数的get请求,服务端接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从前端拿到数据
2、 跨域资源共享:允许浏览器向跨源服务器发出XMLhttpRequest请求,克服了ajax只能同源使用的限制 3、 Nginx代理跨域
4、 Node.js中间件代理跨域 5、 Localtion.hash+iframe跨域

48、数组常用方法及作用,至少15个?

1、 Array.join():将数组中的元素连接成一个字符串 2、 Array.push(): 将新元素追加到数组的最后一个位置中
3、 Array.splice(): 根据数组的下标在数组中的任意位置添加或者删除元素
形参1代表根据数组的下标,从第几个元素开始添加或删除。 4、 Array.slice(): 根据数组下标裁切出一个新的数组
5、 Array.forEach(): 该数组方法接收三个形参,第一个形参为数组中的每一项; 第二个形参为数组中每一项的索引下标;
第三个形参为数组本身。 6、 Array.map():循环,分配内存空间存储新数组并返回 7、 Array.filter():
创建一个新的数组,新数组中的元素是通过filter方法检查后再指定数组中符合条件的所有元素并且它不会改变原始数组。
8、 Array.reduce():
接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减(递增),最终为一个值。
9、 Array.every(): 检查所有数组值是否通过测试。 10、 Array.some():检查某些数组值是否通过测试
11、 Array.indexOf():在数组中搜索元素值并返回其位置 12、 Array.find():通过测试函数的第一个数组元素的值
13、 Array.pop():从数组中删除最后一个元素
14、 Array.shift():删除首个数组元素,并把所有的其他元素位移到哦更低的索引
15、 Array.unshift():在开头向数组添加新元素,并反向位移旧元素

49、说说你对vue中mixin的理解?

1、 Mixin是面向对象程序设计语言中的类,提供了方法的实现,其他类可以访问mixin的方法而不必成为其子类
2、 Vue中的mixin是一种非常灵活的方式,用来分发vue组件的可复用功能
3、 本质上就是一个js对象,可以包含组件中的任意功能选项,比如说data、components、methods、created等
4、 将共用的功能以对象的方式传入 mixins选项中,当组件使用
mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来

50、for…in循环和for…of循环的区别?

1、 For in 和 for of 都是可以用于遍历 2、 For in 遍历的是数组的索引index;for of
遍历的是数组的元素值 3、 For in 更适合遍历对象,当然也可以遍历数组,但是会存在一些问题;for of
可以遍历数、数组对象、字符串等拥有迭代器对象的集合 4、 For in 会遍历数组的所有可枚举属性,包括原型;For of
遍历的只是数组内的元素,不包括原型属性和索引 5、 For in 总是得到对象的key或数组、字符串的下标;for
of得到的对象的value或数组、字符串的值

51、Js数据类型判断都有哪几种方式?至少说出5种?它们的区别是什么?

1、 Typeof方法:返回表示数据类型的字符串,无论引用对象是什么类型,都返回Object
2、 Instanceof方法:由构造类型判断出数据类型 3、 Constructor方法:是prototype对象上的属性,指向构造函数
4、 Object.prototype.toString方法:object对象返回的是[Object
object],其他类型需要call,apply来调用 5、 Jquery.type()方法

52、说说你对Object.defineProperty()的理解?

1、Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。IE8不兼容。
2、对象中目前存在的属性描述符有两种形式:数据描述符和存取描述符
3、数据描述符就是一个具有值的属性,该值可写也不可写;存取描述符是由get和set函数所描述的属性
4、数据描述符有value和writeable,存取描述符是由一堆getter和setter函数功能来描述的属性,get返回值被用作属性值,set方法接受唯一参数,并将该参数的新值分配给该属性
5、当使用get或者set方法时,不能使用writable和value两个属性,反之也一样

53、Vue中自定义指令的理解,应用场景有哪些?

1、 指令系统也是计算机硬件的语言系统,也叫机器语言,是系统程序员看到的计算机主要属性
2、 自定义指令也像组件那样存在的钩子函数,bind、inserted、update、componentUpdated、unbind
3、 场景:表单防止重复提交、图片的懒加载、一键copy的功能

54、说说javascript内存泄漏的几种情况?

1、 意外的全局变量
2、 忘记释放的计时器
3、 多处引用,当多个变量引用同一个对象时,有引用没有被清除
4、 闭包的不合理使用
5、 Console.log打印信息内存不被释放

55、大文件如何做断点续传?

由于大文件上传时,像服务器处理数据的能力、请求超时、网络波动等变量会影响我们的用户体验,那么我们就会需要对大文件上传做单独的处理
1、分片上传:就是将所需要上传的文件,按照一定的大小,将整个文件分割成多个数据块来进行分片上传,在上传完成以后再由服务器对上传的文件进行汇总整合成原始的文件
2、断点续传:断点续传指的是再下载或者上传时,将下载或者上传的任务认为的划分为几个部分,每一个部分采用一个线程进行上传或者是下载,如果碰到网络故障问题,用户可以从已经上传或者下载的部分开始继续上传或者下载未完成的部分,而没有必要从头开始上传下载,用户可以节省时间,提高速度。
3、断点续传一般实现方式有两种,服务器端返回,告知从哪开始;浏览器端自行处理。

56、原生js如何实现上拉加载下拉刷新?

js 上拉加载及下拉刷新都依赖于用户交互 1、上拉加载:
1、scrollTop:滚动视窗的高度距离window顶部的距离,它会随着往上滚动而不断增加,初始值是0,它是一个变化的值
2、clientHeight:它是一个定值,表示屏幕可视区域的高度;
3、scrollHeight:页面不能滚动时也是存在的,此时scrollHeight等于clientHeight。
4、scrollHeight表示body所有元素的总长度(包括body元素自身的padding) 一个触底公式:scrollTop +
clientHeight >= scrollHeight 2、下拉刷新: 下拉刷新的本质是页面本身置于顶部时,用户下拉时需要触发的动作
1、监听原生touchstart事件,记录其初始位置的值,e.touches[0].pageY;
2、监听原生touchmove事件,记录并计算当前滑动的位置值与初始位置值的差值,大于0表示向下拉动,并借助CSS3的translateY属性使元素跟随手势向下滑动对应的差值,同时也应设置一个允许滑动的最大值;
3、监听原生touchend事件,若此时元素滑动达到最大值,则触发callback,同时将translateY重设为0,元素回到初始位置

57、说说设备像素、css像素、设备独立像素、dpr、ppi之间的区别?

1 、无缩放情况下,1个CSS像素等于1个设备独立像素
2、设备像素由屏幕生产之后就不发生改变,而设备独立像素是一个虚拟单位会发生改变
3、 PC端中,1个设备独立像素 = 1个设备像素
(在100%,未缩放的情况下)
4、 在移动端中,标准屏幕(160ppi)下 1个设备独立像素 = 1个设备像素
5、 设备像素比(dpr) = 设备像素 / 设备独立像素 6、 每英寸像素(ppi),值越大,图像越清晰

58、谈谈你对BFC的理解?

1、 Bfc就是块级格式化上下文,它是页面中一块渲染区域,并且有一套属于自己的渲染规则
2、 Bfc的目的就是形成一个相对于外界的完全独立的空间,让内部的子元素不会影响到外部的元素
3、 Bfc就是页面上一个隔离的独立容器,容器里边的子元素不会影响外部的元素,反之也是
4、 Bfc的区域不会和浮动的元素区域重叠

59、说说TCP为什么需要三次握手和四次握手?

三次握手是为了建立可靠的数据传输通道,四次挥手则是为了保证等数据完成的被接收完再关闭连接。
1、 三次握手就是指建立一个TCP连接时,需要客户端和服务器总共发送三个包,主要作用就是为了确认双方的接受能力和发送能力是否正常,指定自己的初始化序列为后边的可靠性传送做准备
2、 四次挥手就是指tcp终止一个连接,需要四次挥手,当服务器在收到客户端断开连接的报文后,并不会立即关闭连接,而是先发送一个ACK包告诉客户端收到关闭连接的请求,只有当服务器的所有报文发送完毕以后,才断开连接

60、前端性能优化的手段有哪些?

1、 资源压缩合并,减少http请求
2、 图片优化,使用png体积小
3、 非核心代码异步加载
4、 利用浏览器缓存,资源文件存在本地,下次调用直接从缓存中取出
5、 使用CDN可以分配负载,提高性能
6、 DNS预解析
7、 开启Gzip代码压缩
8、 减少不必要的cookie

61、最少说出三种前端清除浮动的方法?

1、 额外标签法:在需要清除浮动的元素前面放一个空的div,并给这个空div设置属性 clear:both
2、 给父元素设置 overflow 属性 为 hidden 或者 auto
3、 :after利用伪元素清除有浮动的标签->在有浮动的标签前面添加一个块级元素

62、什么是强缓存和协商缓存?

浏览器首次请求资源后,需要再次请求时,浏览器会首先获取该资源缓存的header信息,然后根据Cache-Control和expires来判断该资源在本地缓存否过期。若没过期则直接从本地缓存中获取资源信息,浏览器就不再向服务器重新请求资源,如过期则需重新发送请求,重新缓存资源,更新缓存时间。
1、强缓存是利用http请求头中的Expires和Cache-Control两个字段来进行控制,用来表示资源的缓存时间。Expires是http1.0的规范,它的值是一个GMT格式的绝对时间字符串。
2、协商缓存是服务器用来确定缓存资源是否可用过期。因为服务器需要向浏览器确认缓存资源是否可用,二者要进行通信,而通信的过程就是发送请求,所以在header中就需要有专门的标识来让服务器确认请求资源是否可以缓存访问

63、说说你对栈、队列的理解?应用场景?

1、 栈(stack)又名堆栈,它是一种运算受限的线性表,限定仅在表尾进行插入和删除操作的线性表
2、 栈按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据,具有记忆作用
3、 队列时跟栈十分相似,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作
4、 队列因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出
5、 场景:栈可以使用在函数调用和递归时,还有编译器在对输入的语法进行分析时;队列可以使用遍历一个二叉树时

64、说说你对git rebase 和git merge的理解?区别?

1、 在使用 git 进行版本管理的项目中,当完成一个特性的开发并将其合并到 master 分支时,会有两种方式是git merge和git rebase
2、 git rebase 与 git merge都有相同的作用,都是将一个分支的提交合并到另一分支上,但是在原理上却不相同
3、 git merge将当前分支合并到指定分支:git merge xxx;git rebase合并分支或合并到指定的commit上:git rebase -I
4、 通过merge合并分支会新增一个merge commit,然后将两个分支的历史联系起来; rebase会将整个分支移动到另一个分支上,有效地整合了所有分支上的提交

65、说说git常用的命令有哪些?

1、 git status :时刻掌握仓库当前的状态,是否进行了修改变化
2、 git diff 小说.txt :查看修改的内容操作
3、 git reflog :查看版本号
4、 git log :查看提交历史
5、 git reset --hard 版本号 :穿梭到那个版本号
6、 git checkout – 小说.txt:可以丢弃工作区的修改
7、 rm 文件名:删除文件(没有提交至工作区的文件)
8、 git rm 文件名:删除版本库中的文件
9、 git branch dev :创建dev分支
10、 git branch -a :查看分支以及当前处于哪个分支
11、 git checkout dev :切换到dev分支
12、 git merge dev:将当前分支与dev分支进行合并

66、Vue组件通信?

组件通信指的是发送者通过某种媒体以某种格式来传递信息到收信者以达到某个目的
分类:父子组件之间的通信、兄弟组件之间的通信、祖孙与后代组件之间的通信、非关系组件间之间的通信
vue中8种常规的通信方案:
1、通过 props 传递:子组件设置props属性,定义接收父组件传递过来的参数,父组件在使用子组件标签中通过字面量来传递值
2、通过 $emit 触发自定义事件:子组件通过$emit触发自定义事件,$emit第二个参数为传递的数值,父组件绑定监听器获取到子组件传递过来的参数
3、使用 ref:父组件在使用子组件的时候设置ref,父组件通过设置子组件ref来获取数据
4、EventBus:创建一个中央事件总线EventBus,兄弟组件通过$emit触发自定义事件,$emit第二个参数为传递的数值
另一个兄弟组件通过$on监听自定义事件
5、$parent $root:通过共同祖辈$parent或者$root搭建通信桥连
6、attrs 与 listeners:设置批量向下传属性$attrs $listeners,包含了父级作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。可以通过 v-bind=“$attrs” 传⼊内部组件
7、Provide 与 Inject:在祖先组件定义provide属性,返回传递的值,在后代组件通过inject接收组件传递过来的值
8、Vuex:作用相当于一个用来存储共享变量的容器

67、说说你对vuex的理解?写出其原理的核心代码?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
vuex五大核心属性:state,getter,mutation,action,module
1、state:存储数据,存储状态;在根实例中注册了store 后,用this.$store.state来访问;对应vue里面的data;存放数据方式为响应式,vue组件从store中读取数据,如数据发生变化,组件也会对应的更新。
2、getter:可以认为是 store 的计算属性,它的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
3、mutation:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
4、action:包含任意异步操作,通过提交 mutation 间接更变状态。
5、module:将 store 分割成模块,每个模块都具有state、mutation、action、getter、甚至是嵌套子模块。

68、props和state相同点和不同点?render方法在哪些情况下会执行?

不同点:
1.props不可以在组件内部修改,但state可以在组件内部修改
2.可以从父组件修改自组件的props,而不能从父组件修改自组件的state
相同点:
1.props和state都是导出HTML的原始数据。
2.props和state都是确定性的,如果我们写的组件为同一props和state的组合3.生成了不同的输出,那木我们肯定在哪里做错了
4.props和state都会触发渲染更新
5.props和state都是纯JS对象(用typeof来判断,结果都是object)
6.可以从父组件得到初始值props和state的初始值
render在哪些情况下执行?
1、类组件调用setState修改状态时
2、函数组件通过useState Hook修改状态时
3、类组件重新渲染时
4、函数组件重新渲染时

69、react新出来两个钩子函数是什么?和删掉的will系列有什么区别?

React新增的两个生命周期钩子函数?
1、getDerviedStateFromProps
作用:从props中获取衍生的state
2、getSnapshotBeforeUpdate
作用:在组件更新前获取快照,一般结合componentDidUpdate使用,getSnapBeforeUpdate中返回值将作为第三参数传递给componentDidUpdate
它和componentDidUpdate将render夹在中间,其实它的核心作用就是在render改变dom之前,记录更新前的dom信息传递给componentDidUpdate。
二、React新的生命周期去除的钩子函数?
1、componentWillMount
2、componentWillReceiveProps
3、componentWillUpdate
总结
1、componentWillMount中可能需要做的事(一些数据初始化的操作就应该放在这个钩子中处理),constructor与componentDidMount也能做,甚至做的更好,此方法被废弃。
2、componentWillReceiveProps实际行为与命名并不相符,由于不稳定性已由getDerivedStateFromProps代替;
3、而componentWillUpdate同等理由被getSnapshotBeforeUpdate代替

70、CDN的特点及意义?

1、CDN 意为内容分发网络,是基于现有网络的智能虚拟网络,分布在世界各地的边缘服务器上。基本思路是避免互联网上可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输更快更稳定。
2、CDN 表示将数据从原始服务器复制到其他服务器。当用户访问时,他们可以在复制了数据内容的服务器上进行访问。其目的是使用户能够更快更好地获取所需内容,解决网络拥塞情况,提高用户访问网站的响应速度。CDN 加速成本低,速度快,适合访问量比较大的网站。
特点:
1.本地缓存加速:提高了企业网站(尤其是包含大量图片和静态页面的网站)的访问速度,大大提高了上述网站的稳定性。
2.镜像服务:消除了不同运营商之间互联瓶颈带来的影响,实现了跨运营商的网络加速,保证了不同网络的用户都能获得良好的接入质量。
3.远程加速:远程访问用户根据DNS负载均衡技术智能自动选择缓存服务器,选择最快的缓存服务器加速远程访问。
4.带宽优化:自动生成服务器的远程镜像缓存服务器。远程用户访问时,可以从缓存服务器读取数据,减少远程访问的带宽,分担网络流量,减轻原WEB服务器的负载。
5.集群抗攻击:广泛分布的CDN 节点加上节点间的智能冗余机制,可以有效防止黑客入侵,降低各种D.D.o.S攻击对网站的影响,同时保证更好的服务质量。

71、什么是闭包,应用场景是什么?

1、闭包就是能够读取其他函数内部变量的函数,说白了闭包就是个函数,只不过是处于其他函数内部而已。
2、由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“
应用场景:
1、模仿块级作用域:计时器的应用、打印一组li标签的下标
2、埋点计数器:产品做一些常用的数据采集方法
3、柯里化:将一个多参数的函数转换为单参数函数的办法

72、介绍一下你对浏览器内核的理解?

内核主要分为渲染引擎和js引擎
1、渲染引擎:负责取得网页的内容(HTML,XML和图像等),整理讯息(例如css),以及计算网页的显示方式,然后输出到显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不同。所有网页浏览器、电子邮件客户端以及它需要编辑、显示网络内容的应用程序都需要内核
2、JS引擎:解析和执行JavaScript来实现网页的动态效果
最开始渲染引擎和js引擎并没有区分很明确,后来js引擎越来越独立,内核就倾向与只指渲染引擎

73、 清除浮动的几种方式?各自的优缺点?

清除浮动:为了解决父元素因为子级元素浮动引起的内部高度塌陷的问题
方式:
1、额外标签法(在最后一个浮动标签后,新添加一个标签,给它设置clear:both;)优点:通俗易懂更加方便;缺点:添加无意义标签,语义化差
2、父级添加overflow属性(父元素添加overflow:hidden) 优点:代码简洁;缺点:内容增多时容易造成不会自动换行导致内容被隐藏掉,无法显示要溢出的元素
3、使用after伪元素清除浮动 优点:符合闭合浮动思想,结构语义化正确;缺点:IE6-7不支持伪元素
4、使用before和after双伪元素清除浮动 优点:代码更加简洁;缺点:用zoom:1触发haslayout

74、 如果需要手动写动画,你认为最小时间间隔是多久,为什么?

多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms。为了浏览器的渲染和用户体验的话,最小设置0.1-0.3s最佳

75、说说Real DOM和Virtual DOM的区别?优缺点?

1、Real DOM,真实DOM, 意思为文档对象模型,是一个结构化文本的抽象,在页面渲染出的每一个结点都是一个真实DOM结构
2、Virtual Dom,本质上是以 JavaScript 对象形式存在的对 DOM 的描述
3、创建虚拟DOM目的就是为了更好将虚拟的节点渲染到页面视图中,虚拟DOM对象的节点与真实DOM的属性一一照应
4、两者的区别如下:
虚拟DOM不会进行排版与重绘操作,而真实DOM会频繁重排与重绘
虚拟DOM的总损耗是“虚拟DOM增删改+真实DOM差异增删改+排版与重绘”,真实DOM的总损耗是“真实DOM完全增删改+排版与重绘”
优缺点?
真实DOM的优势:易用
缺点:
1、效率低,解析速度慢,内存占用量过高
2、性能差:频繁操作真实DOM,易于导致重绘与回流
使用虚拟DOM的优势如下:
1、简单方便:如果使用手动操作真实DOM来完成页面,繁琐又容易出错,在大规模应用下维护起来也很困难
2、性能方面:使用Virtual DOM,能够有效避免真实DOM数频繁更新,减少多次引起重绘与回流,提高性能
3、跨平台:React借助虚拟DOM, 带来了跨平台的能力,一套代码多端运行
缺点:
1、在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化
2、首次渲染大量DOM时,由于多了一层虚拟DOM的计算,速度比正常稍慢

76、说说react的事件机制?

1、react自身实现了一套自己的事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等,虽然和原生的是两码事,但也是基于浏览器的事件机制下完成的。
2、React 上注册的事件最终会绑定在document这个 DOM 上,而不是 React 组件对应的 DOM(减少内存开销就是因为所有的事件都绑定在 document 上,其他节点没有绑定事件)
3、React 自身实现了一套事件冒泡机制,所以这也就是为什么我们 event.stopPropagation()无效的原因。
4、React 通过队列的形式,从触发的组件向父组件回溯,然后调用他们 JSX 中定义的 callback
5、React 有一套自己的合成事件 SyntheticEvent

77、说说你对fiber架构的理解?解决了什么问题?

React Fiber 是 Facebook 花费两年余时间对 React 做出的一个重大改变与优化,是对 React 核心算法的一次重新实现。
在react中,主要做了以下的操作:
1、为每个增加了优先级,优先级高的任务可以中断低优先级的任务。然后再重新,注意是重新执行优先级低的任务
2、增加了异步任务,调用requestIdleCallback api,浏览器空闲的时候执行
dom diff树变成了链表,一个dom对应两个fiber(一个链表),对应两个队列,这都是为找到被中断的任务,重新执行
3、从架构角度来看,Fiber 是对 React核心算法(即调和过程)的重写
4、从编码角度来看,Fiber是 React内部所定义的一种数据结构,它是 Fiber树结构的节点单位,也就是 React 16 新架构下的虚拟DOM

78、说说react diff的原理是什么?

1、跟Vue一致,React通过引入Virtual DOM的概念,极大地避免无效的Dom操作,使我们的页面的构建效率提到了极大的提升而diff算法就是更高效地通过对比新旧Virtual DOM来找出真正的Dom变化之处
运作流程主要分为三层:tree层、component层、element层
1、tree层:tree层对于DOM节点的跨层级移动的操作忽略,只对相同层级的DOM节点进行比较,一旦发现节点不存在,直接删除该节点以及以下的所有子节点
2、component层:遇到同一个类型的组件遵循tree diff,进行层级对比,遇到不同类型的组件,直接将这个不同的组件判断为脏组件,并且替换该组件之下的所有的子节点,当知道这个组件的虚拟DOM没有任何变化,就可以手动使用,shouldComponentUpdate来判断是否需要进行diff,进一步提升了diff效率和性能
3、element层:低于同一层级,面对全新节点,可以实现插入的操作;面对多余的节点,执行删除操作;面对换位的节点,执行移动的操作

79、如何使用css实现一个三角形?

1、border:给定一个宽度和高度都为 0 的元素,其 border 的任何值都会直接相交,我们可以利用这个交点来创建三角形。也就是说,border属性是三角形组成的,如果想要一个指向右面的三角形,可以让 border 的左边可见,其他边都设置为透明:
2、linear-gradient:linear-gradient 需要结合 background-image 来实现三角形,下面就来逐步使用渐变实现一个三角形。
3、clip-path:clip-path 就是使用它来绘制多边形(或圆形、椭圆形等)并将其定位在元素内。实际上,浏览器不会绘制 clip-path 之外的任何区域,因此我们看到的是 clip-path 的边界。
4transform: rotate 配合 overflow: hidden 绘制三角形

80、shouldComponentUpdate有什么作用?

1、根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染。
2、eact中props,state值的变化,会导致组件重新渲染。使用shouldComponentUpdate就是为了减少render不必要的渲染。 返回布尔值,然后做 Virtual DOM 比较,并得出是否需要做真实 DOM 更新

81、说说你对git rebase 和git merge的理解?区别?

1、在使用git管理版本的项目中,当完成一个特性的开发,并将其合并到master分支,就会使用到git rebase 和git merge
2、两个都有相同的作用:将一个分支的提交合并到另一个分支上,但是原理不一样
3、Git merge将当前分支合并到指定分支:git merge xxx;git rebase合并到指定的commit上:git rebase -I
4、通过merge合并的分支会新增一个merge commit,,然后将两个分支的历史联系起来;rebase会将整个分支移动到另一个分支上,有效的整合了所有分支上的提交

82、在使用redux过程中,如何防止定义的action-type的常量重复?

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。
Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

83、说说React中的虚拟dom?在虚拟dom计算的时候diff和key之间有什么关系?

1、实际上它只是一层对真实DOM的抽象,以JavaScript对象(VNode节点)作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作时这棵树映射到真实环境上,创建虚拟DOM就是为了更好将虚拟的节点渲染到页面视图中,所以虚拟DOM对象的节点与真实DOM的属性一一照应
2、通过JS模拟网页文档节点,生成JS对象树(虚拟DOM),然后再进行一步生成真实的DOM树,再绘制到屏幕。如果后面有内容发生改变,React会重新生成一棵全新的虚拟DOM树,再与前面的虚拟DOM树进行比对diff,把差异的部分打包成patch,再应用到真实DOM,然后渲染到屏幕浏览器。
在虚拟dom计算的时候diff和key之间有什么关系:
1、React需要同时维护两棵虚拟DOM树:一棵表示当前的DOM结构,另一棵在React状态变更将要重新渲染时生成。React通过比较这两棵树的差异,决定是否需要修改DOM结构,以及如何修改。这种算法称作Diff算法。
2、key 当同一层级的某个节点添加了对于其他同级节点唯一的key属性,当它在当前层级的位置发生了变化后。react diff算法通过新旧节点比较后,如果发现了key值相同的新旧节点,就会执行移动操作(然后依然按原策略深入节点内部的差异对比更新),而不会执行原策略的删除旧节点,创建新节点的操作。这无疑大大提高了React性能和渲染效率。

84、React的props.children使用map函数来遍历会收到异常显示,为什么?应该 如何遍历?

1、当前组件没有子节点数据类型就是undefined,
2、有一个子节点数据类型就是object 。
3、有多个子节点的时候才会是array ,只有在多个节点的时候才可以直接调用map方法,react资深提供了一个react.children.map()方法,可以安全遍历子节点对象。

85、谈谈你对immutable.js的理解?

1、Immutable.js就是react中用来做性能优化的
2、在react中使用immutable可以减少页面的一些不必要的渲染,不需要像react中进行深度对比而进行渲染
3、immutable可以直接快速的进行对比,完成渲染,提升了渲染的效率,降低了性能的消耗
4、Immutable不可改变的,在计算机中,即指一旦创建,就不能再被更改的数据
对 Immutable对象的任何修改或添加删除操作都会返回一个新的 Immutable对象
Immutable 实现的原理是 Persistent Data Structure(持久化数据结构):
1、用一种数据结构来保存数据
2、当数据被修改时,会返回一个对象,但是新的对象会尽可能的利用之前的数据结构而不会对内存造成浪费

86、redux本来是同步的,为什么它能执行异步代码?实现原理是什么?中间件的 实现原理是什么?

1、Redux-thunk这个中间件支持异步操作
2、执行异步的操作首先需要下载一个thunk,通过thunk来进行异步的一个操作,支持异步操作,可以使用dispatch和getState来进行数据的获取或状态
3、Redux是一个状态管理库,redux的核心是store,actions,reducers三个部分
4、通过dispatch发放到任务的actions中,在actions中返回一个promise对象,再通过dispatch派发到reducers中
5、在reducers中通过传递type和data来进行判读

87、redux中同步action与异步action最大的区别是什么?

1、同步action:执行了dispatch函数之后,对应的reducer纯函数立即得到执行,reducer执行完了之后,state立即就改变了,此时用store.getState函数,取到的是最新的state值;
2、异步action:原则上redux并没有提供异步action的处理方案,异步的action需要依赖第三方的中间件解决(如redux-thunk),dispatch了一个异步action(本质上是dispatch的一个函数)之后,目标state并不会立即响应,而是要看异步函数内部的逻辑,来决定state什么时候响应。
3、区别:
首先区别redux和react-redux,redux是一个单独的模块,在其他框架中也能使用,而react-redux是为react管理数据而生。
redux的设计思想:web应用是一个状态机,视图与状态是一一对应的,所有的状态,保存在一个对象里面

88、redux-saga和redux-thunk的区别与使用场景?

1、使用redux-thunk的代码,当我们返回的是函数时,store会帮我们调用这个返回的函数,并且把dispatch暴露出来供我们使用。对于redux-thunk的整个流程来说,它是等异步任务执行完成之后,我们再去调用dispatch,然后去store去调用reduces
2、使用了redux-saga的代码,当我们dispatch的action类型不在reducer中时,redux-saga的监听函数takeEvery就会监听到,等异步任务有结果就执行put方法,相当于dispatch,再一次触发dispatch。对于redux-saga的整个流程来说,它是等执行完action和reducer之后,判断reducer中有没有这个action
区别:
1、redux-thunk和redux-saga处理异步任务的时机不一样。对于redux-saga,相对于在 2、redux的action基础上,重新开辟了一个 async action的分支,单独处理异步任务
3、saga 自己基本上完全弄了一套 asyc 的事件监听机制,代码量大大增加,从我自己的使用体验来看 redux-thunk 更简单,和 redux 本身联系地更紧密。

89、为什么普通的for循环比forEach循环性能要高?

1、for循环就是通过下标,对循环中的代码反复执行,功能强大,可以通过index取得元素。处理比较复杂的处理的时候比较方便
2、forEach()循环方法用于调用数组的每个元素,并将元素传递给回调函数。foreach有的也叫做增强for循环,forEach其实是for循环的一个特殊简化版。forEach循环对于空的数组是不会执行回调函数的。
区别:
1、遍历:for循环按照顺序进行遍历,forEach使用iterator迭代器遍历
2、数据结构:for循环是随机访问元素,foreach是顺序链表访问元素
3. 性能上:对于数组arraylist来说,是顺序表,使用for循环可以进行顺序访问,速度比较快;使用foreach循环会比for循环稍微慢一点。对于linedlist来说,是单链表,使用for循环每次都要从第一个元素读取next域来读取,速度非常慢;使用foreach可以直接读取当前的节点,数据较快。

90、移动端1像素的解决方案?

在移动端web开发中,UI设计稿中设置边框为1像素,前端在开发过程中如果出现border:1px,测试会发现在某些机型上,1px会比较粗,即是较经典的移动端1px像素问题
方案:
1、小数:0.5px,相信浏览器肯定是会慢慢支持的;目前而言,如果能用的话,可以hack一下;
2、阴影,border-img的方案不建议使用
3、背景图片和缩放可以在项目中配合使用,如单个线条使用缩放,四条框用背景图片模拟,额,如果要圆角的话,无能无力了
4、建议采用transform和伪类

91、弹性盒中的缩放机制是怎样?

1、弹性盒的项目设置flex-grow属性定义项目的放大比例,默认值为0,值越大,放大越厉害,且不支持负值;
2、而flex-shrink属性定义项目的缩小比列,默认值为1,数值越大,缩小越厉害,同样不支持负值;
3、flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间,浏览器根据这个属性,计算主轴是否有多余空间。他的默认值为auto,也就是项目的本来大小。

92、说说你对vue中mixin的理解?

1、 Mixin是面向对象程序设计语言中的类,提供方法的实现,其他1的类可以访问mixin中的方法而不必称为其子类
2、 Vue中mixin是用来分发vue组件的可复用功能
3、 本质上就是一个js对象,可以包含组件中的任意功能选项,比如说data、component、methods、created等
4、 将公用的功能以对象的方式传入mixins选项中,当组件使用mixins对象时,所有的mixins对象的选项都被混入该组件本身的选项中

93、for…in循环和for…of循环的区别?

For in和for of都属于遍历
1、for in 遍历时数组的索引index,for of遍历的时数组的元素值
2、for in更适合遍历对象,也可以遍历数组,会存在一些问题;for of 数组,对象等一些拥有迭代器对象的集合
3、for in 总是得到对象的键或者数组、字符串的下标;for of得到的对象的值或者数组、字符串的值

94、什么是发布订阅模式,写出其核心实现代码?

1、发布订阅模式:订阅者(Subsciber)通过事件注册(Subscribe)将订阅事件提交到调度中心(Topic),调度中心保存好订阅者的注册信息(回调函数),每当发布者(Publisher)发布事件的时候,通过事件发布(Publish)将发布的消息提交到调度中心,然后调度中心统一处理订阅者注册该事件的消息(执行注册时的回调函数)


2、实现:
	//实例化一个发布订阅模式,多个new,可以做到事件隔离,正常一个项目一个就够了
    const pub1 = new Pubsub()
    //调用 示例 
    pub1.topic("on-sleep)  //创建一个睡觉的订阅主题
    //同学1 订阅睡觉
    pub1.subscribe("on-sleep",(a)=>{
        console.log("sleep")
        console.log(a)
    })
    //同学2 订阅睡觉  回调不同
    pub1.subscribe("on-sleep",(a)=>{
        console.log("sleep2”)
        console.log(a)
    })
 
    setTimeout(()=>{
        //时间差不多了,通知他们该睡觉了!
        pub1.publish("on-sleep",{info:"该睡觉啦!"})
    },2000)

95、说一说你对视口的理解?

1、在一个浏览器中,看到的区域就是视口(viewport)
2、在PC端页面中,不需要对视口进行区分,因为布局视口和视觉视口是同一个
3、但在移动端,你布局的视口和可见的视口是不一样的因为移动端的网页窗口往往比较小,我们可能会希望一个大的网页在移动端可以完整的显示;
4、所以在默认情况下,移动端的布局视口是大于视觉视口的
5、所以在移动端,我们将视口分成三种情况
1、布局视口(layout viewport)
2、视觉视口(visual layout)
3、理想视口(ideal layout)

96、说说你对useEffect的理解,可以模拟哪些生命周期?

1、使用钩子函数useEffect可以实现组件的副作用。useEffect(希望执行的动作, [组件状态的列表]);第二个参数用来处理useEffect调用的时机,是一个数组,数组内是组件状态的列表。
2、useEffect模拟componentDidMount:当useEffect的第二个参数传入空列表时,相当于模拟生命周期函数componentDidMount。这个副作用仅在组件第一次挂载ui的时候调用一次。用它来模拟组件初次挂载时,访问api、获得数据:
3、useEffect模拟componentDidUpdate:如果在使用useEffect时不带上第二个参数,就相当于模拟了生命周期函数componentDidUpdate。每次渲染结束的时候都会被调用。
4、useEffect模拟componentWillUnmount,在useEffect中返回一个函数用于模拟component WillUnMount

97、说说React中setState和replaceState的区别?

1、setState用于设置状态对象
2、两个参数:nextState,将要设置的新状态,该状态会和当前的state合并;callback,可选参数,回调函数。该函数会在setState设置成功,且组件重新渲染后调用。
3、合并nextState和当前state,并重新渲染组件。setState是React事件处理函数中和请求回调函数中触发UI更新的主要方法。
4、replaceState()方法与setState()类似,但是方法只会保留nextState中状态,原state不在nextState中的状态都会被删除
5、两个参数:nextState,将要设置的新状态,该状态会替换当前的state。callback,可选参数,回调函数。该函数会在replaceState设置成功,且组件重新渲染后调用。

  1. setState 是修改其中的部分状态,相当于 Object. assign,只是覆盖,不会减少原来的状态;
  2. replaceState 是完全替换原来的状态,相当于赋值,将原来的 state 替换为另一个对象,如果新状态属性减少,那么 state 中就没有这个状态了。

98、说说react中onClick绑定后的工作原理?

当组件元素绑定onClick事件之后:
1、react会对事件先进行注册,将事件统一注册到document上
2、根据组件唯一的表示key来对事件函数进行存储
3、统一的指定,dispatchEvent回调函数
4、存储事件回调:react会将click这个事件统一存放在一个对象中,回调函数中存储采用键值对的方式存储在对象中,key是组件唯一标识id,value对应的事件就是回调函数,通过组件的key就能回到相对应的函数了。

99、什么是垂直外边距合并?说说合并后的几种情况?

1、垂直外边距合并:当两个存志外边距相遇时,将形成一个外边距,合并后的外边距高度等于两个发生合并的外边距的高度中的较大者
2、注意:只有普通的文档流中的块级元素的垂直外边距才会发生外边距合并,行内框,浮动框或者绝对定位之间的外边距不会合并
情况:
1、当相邻的元素垂直外边距合并时候:如果上边的元素有下外边距,下边的元素有上外边距,那么他们之间的垂直间距不是bottom和top之间的和,而是两者中较大者,这种现象被称为外边距塌陷
2、当嵌套块元素垂直外边距合并:如果父元素没有上内边距以及边框,那么父元素上外边距会与子元素的上外边距发生合并,合并后的外边距为两者中的较大者,就是父元素的上外边距为0,也会合并
解决方法:可以为父元素定义1像素的上边框或上内边距

100、useEffect的依赖为引用类型如何处理?

1、使用 ‘use-deep-compare-effect’ :他可以进行深比较,使用方法也很简单, import useDeepCompareEffect from ‘use-deep-compare-effect’ 之后用useDeepCompareEffect 替换掉 原有的 useEffect 即可。
2、也可以使用 useRef这个钩子来解决上述问题,useRef的特性是跨渲染周期保存数据
3、用useRef保存了之前的数据, useEffect中的依赖以然为引用类型, 每次obj发生改变都会调用执行函数,但是执行函数中多了一个判断, prevObj是上一次渲染时obj的值, 用prevObj中的某个key与此次obj中的某个key做对比,满足条件后做其他操作

101、知道react里面的createPortal么,说说其使用场景?

1、Portal ,将子节点渲染到存在于父组件以外的 DOM 节点。
2、ReactDOM.createPortal(child, container)
第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。
2、Portals 适合脱离文档流(out of flow) 的组件,特别是 position: absolute 与 position: fixed的组件。比如模态框,通知,警告,goTop 等

102、Provider和connect的底层原理实现,写出其核心代码?

1、Provider和connect是React Redux库中的两个重要概念。
2、Provider是一个React组件,它允许我们将store传递给整个应用程序。
3、Connect是一个高阶函数,它允许我们将组件连接到Redux store。
4、Provider的底层原理是使用React的Context API,它允许我们在组件树中传递数据而不必手动将它们传递给每个组件。
5、Connect的底层原理是使用React Redux的connect函数,它接受一个mapStateToProps函数和一个mapDispatchToProps函数,并返回一个新的函数,该函数将Redux store中的状态和操作作为props传递给组件。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值