目录
目录
十.说说你对Object.defineProperty()的理解?
一.调和阶段setState干了什么?
当调用 setState 时,React 会做的第一件事情是将数据传递给 setState 的对象合并到组件的当前状态
这将启动一个称为和解(reconciliation)的过程。和解(reconciliation)的最终目标是以最有效的方式,根据这个新的状态来更新UI。 为此,React将构建一个新的 React 元素树(您可以将其视为 UI 的对象表示)
二.说说你对fiber架构的理解?解决了什么问题?
React Fiber 是 Facebook 花费两年余时间对 React 做出的一个重大改变与优化,是对 React 核心算法的一次重新实现。从Facebook在 React Conf 2017 会议上确认,React Fiber 在React 16 版本发布
在react
中,主要做了以下的操作:
- 为每个增加了优先级,优先级高的任务可以中断低优先级的任务。然后再重新,注意是重新执行优先级低的任务
- 增加了异步任务,调用requestIdleCallback api,浏览器空闲的时候执行
- dom diff树变成了链表,一个dom对应两个fiber(一个链表),对应两个队列,这都是为找到被中断的任务,重新执行
架构角度来看,Fiber
是对 React
核心算法(即调和过程)的重写
从编码角度来看,Fiber
是 React
内部所定义的一种数据结构,它是 Fiber
树结构的节点单位,也就是 React 16
新架构下的虚拟DOM
一个 fiber
就是一个 JavaScript
对象,包含了元素的信息、该元素的更新操作队列、类型,
如何解决
Fiber
把渲染更新过程拆分成多个子任务,每次只做一小部分,做完看是否还有剩余时间,如果有继续下一个任务;如果没有,挂起当前任务,将时间控制权交给主线程,等主线程不忙的时候在继续执行
即可以中断与恢复,恢复后也可以复用之前的中间状态,并给不同的任务赋予不同的优先级,其中每个任务更新单元为 React Element
对应的 Fiber
节点
实现的上述方式的是requestIdleCallback
方法
window.requestIdleCallback()
方法将在浏览器的空闲时段内调用的函数排队。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应
首先 React 中任务切割为多个步骤,分批完成。在完成一部分任务之后,将控制权交回给浏览器,让浏览器有时间再进行页面的渲染。等浏览器忙完之后有剩余时间,再继续之前 React 未完成的任务,是一种合作式调度。
该实现过程是基于 Fiber
节点实现,作为静态的数据结构来说,每个 Fiber
节点对应一个 React element
,保存了该组件的类型(函数组件/类组件/原生组件等等)、对应的 DOM 节点等信息。
作为动态的工作单元来说,每个 Fiber
节点保存了本次更新中该组件改变的状态、要执行的工作。
三.说说Connect组件的原理是什么?
connect组件的本质是一个高阶函数,它是真正与store进行数据交互的组件,包在我们的容器组件的外一层,接收上面 Provider 提供的 store 里面的 state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。
原理:
首先传入mapStateToProps、mapDispatchToProps,然后返回一个生产Component的函数,然后再将真正的Component作为参数传入wrapWithConnect,这样就生产出一个经过包裹的Connect组件
四.为什么react元素有一个$$type属性?
简单理解就是防止受到XSS攻击。这种攻击取决于现有的服务器漏洞,
它的修复方法是对每一个React元素使用Symbol来进行标记。
五.React性能优化的手段有哪些
-
服务端渲染
采用服务端渲染端方式,可以使用户更快的看到渲染完成的页面
服务端渲染,需要起一个node
服务,可以使用express
、koa
等,调用react
的renderToString
方法,将根组件渲染成字符串,再输出到响应中
-
避免使用内联函数
如果我们使用内联函数,则每次调用render
函数时都会创建一个新的函数实例
-
使用 React Fragments 避免额外标记
用户创建新组件时,每个组件应具有单个父标签。父级不能有两个标签,所以顶部要有一个公共标签,所以我们经常在组件顶部添加额外标签div
这个额外标签除了充当父标签之外,并没有其他作用,这时候则可以使用fragement
其不会向组件引入任何额外标记,但它可以作为父级标签的作用,
-
使用 Immutable
使用 Immutable
可以给 React
应用带来性能的优化,主要体现在减少渲染的次数
在做react
性能优化的时候,为了避免重复渲染,我们会在shouldComponentUpdate()
中做对比,当返回true
执行render
方法
Immutable
通过is
方法则可以完成对比,而无需像一样通过深度比较的方式比较
-
懒加载组件
从工程方面考虑,webpack
存在代码拆分能力,可以为应用创建多个包,并在运行时动态加载,减少初始包的大小
而在react
中使用到了Suspense
和 lazy
组件实现代码拆分功能
-
事件绑定方式
我们了解到四种事假绑定的方式
从性能方面考虑,在render
方法中使用bind
和render
方法中使用箭头函数这两种形式在每次组件render
的时候都会生成新的方法实例,性能欠缺
而constructor
中bind
事件与定义阶段使用箭头函数绑定这两种形式只会生成一个方法实例,性能方面会有所改善
六.React render方法的原理,在什么时候会触发?
在类组件和函数组件中,render函数的形式是不同的。
在类组件中render函数指的就是render方法;而在函数组件中,指的就是整个函数组件。
在render函数中的jsx语句会被编译成我们熟悉的js代码
在render过程中,React 将新调用的 render函数返回的树与旧版本的树进行比较,这一步是决定如何更新 DOM 的必要步骤,然后进行 diff 比较,更新 DOM树
触发机制:
类组件调用 setState 修改状态 函数组件通过useState hook修改状态。函数组件通过useState这种形式更新数据,当数组的值不发生改变了,就不会触发render
总结:
render函数里面可以编写JSX,转化成createElement这种形式,用于生成虚拟DOM,最终转化成真实DOM
在React 中,类组件只要执行了 setState 方法,就一定会触发 render 函数执行,函数组件使用useState更改状态不一定导致重新render
组件的props 改变了,不一定触发 render 函数的执行,但是如果 props 的值来自于父组件或者祖先组件的 state
在这种情况下,父组件或者祖先组件的 state 发生了改变,就会导致子组件的重新渲染
所以,一旦执行了setState就会执行render方法,useState 会判断当前值有无发生改变确定是否执行render方法,一旦父组件发生渲染,子组件也会渲染说说你对vue中mixin的理解
七.说说你对vue中mixin的理解
mixin是什么
Mixin
是面向对象程序设计语言中的类,提供了方法的实现。其他类可以访问mixin
类的方法而不必成为其子类
Mixin
类通常作为功能模块使用,在需要该功能时“混入”,有利于代码复用又避免了多继承的复杂
Vue中的mixin
先来看一下官方定义mixin(混入),提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。
本质其实就是一个js对象,它可以包含我们组件中任意功能选项,如data、components、methods 、created、computed等等
我们只要将共用的功能以对象的方式传入 mixins选项中,当组件使用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来
在Vue中我们可以局部混入跟全局混入
八.for...in循环和for...of循环的区别?
1. for-in循环
for-in循环主要用于遍历对象,for()中的格式:for(keys in zhangsan){}
keys表示obj对象的每一个键值对的键!!所有循环中,需要使用obj[keys]来取到每一个值!!!for-in 循环,遍历时不仅能读取对象自身上面的成员属性,也能延续原型链遍历出对象的原型属性所以,可以使用hasOwnProperty判断一个属性是不是对象自身上的属性obj.hasOwnProperty(keys)==true 表示这个属性是对象的成员属性,而不是原先属性。
2. for-of循环
ES6 借鉴 C++、Java、C# 和 Python 语言,引入了for…of循环,作为遍历所有数据结构的统一的方法。
一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,就可以用for…of循环遍历它的成员。也就是说,for…of循环内部调用的是数据结构的Symbol.iterator方法。
for…of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、后文的 Generator 对象,以及字符串
九.Js数据类型判断都有哪几种方式?它们的区别是什么?
1.typeof
typeof它返回值是一个字符串,该字符串说明运算数的类型。返回结果只有以下几种:number,string,boolean,object,undfined,function
可以使用typeof判断变量是否存在(比如 if(typeof a!=“undfined”){ xxx }),而不要去使用if(a),因为a不存在(未声明)会报错。
无法判断对象和数组,还有null,因为都返回的是object
2.Object.prototype.tostring().call()
在判断数据类型时,我们称 Object.prototype.toString 为 “万能方法” “终极方法”,工作中也是比较常用而且准确。
对于Object.prototype.toString() 方法,会返回一个形如 “[object XXX]” 的字符串
3.instanceof
instanceof 是用来 判断数据是否是某个对象的实例,返回一个布尔值
。
4.Array.isArray()
js中的isArray()是Array类型的一个静态方法,使用它可以判断一个值是否为数组。
返回一个布尔值。
5.jquery.type()
万能的方法如果对象是undefined或null,则返回相应的“undefined”或“null”。
6.constructor
constructor是prototype对象上的属性,指向构造函数,
十.说说你对Object.defineProperty()的理解?
定义:Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
该方法接受三个参数
-
第一个参数是
obj
:要定义属性的对象, -
第二个参数是
prop
:要定义或修改的属性的名称或Symbol
, -
第三个参数是
descriptor
:要定义或修改的属性描述符
函数的第三个参数 descriptor
所表示的属性描述符有两种形式:数据描述符和存取描述符。
-
数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。
-
存取描述符是由
getter
函数和setter
函数所描述的属性。
一个描述符只能是这两者其中之一;不能同时是两者。
这两种同时拥有下列两种键值:
configurable
: 是否可以删除目标属性或是否可以再次修改属性的特性(writable
, configurable
, enumerable
)。设置为true
可以被删除或可以重新设置特性;设置为false
,不能被可以被删除或不可以重新设置特性。默认为false
。
enumerable
: 当且仅当该属性的 enumerable
键值为 true
时,该属性才会出现在对象的枚举属性中。默认为 false
。
十一.谈谈你对WebSocket的理解
一、什么是websocket
WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)
它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的
Websocket是一个持久化的协议
二、websocket的原理
websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信
在websocket出现之前,web交互一般是基于http协议的短连接或者长连接
websocket是一种全新的协议,不属于http无状态协议,协议名为"ws"
十二.说说你对事件循环event loop的理解
任务在主线程不断进栈出栈的一个循环过程。任务会在将要执行时进入主线程,在执行完毕后会退出主线程
十三.前端跨域的解决方案
通过jsonp跨域 document.domain + iframe跨域 location.hash + iframe window.name + iframe跨域 postMessage跨域 跨域资源共享(CORS) nginx代理跨域 nodejs中间件代理跨域 WebSocket协议跨域
十四.说说你对webSocket的理解?
理解 WebSocket
是HTML5
下一种新的协议(websocket
协议本质上是一个基于tcp
的协议)
它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的
Websocket是一个持久化的协议
原理 websocket
约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp
的连接,从而方便它们之间的通信
在websocket
出现之前,web
交互一般是基于http协议
的短连接或者长连接
websocket
是一种全新的协议,不属于http无状态协议,协议名为"ws"