前端面试题
目录
- 前端面试题
- React相关
- 1.说说React生命周期中有哪些坑?为什么要溢出will相关生命周期
- 2. 说说Real diff算法是怎么运作的,从tree层到component层到element层分别讲解?
- 3.调和阶段setState干了什么
- 4.css3的新特性都有哪些
- 5.说说redux的工作流程
- 6.React合成事件的原理,有什么好处和优势?
- 7.为什么react元素有一个$$type属性?
- 8.react的性能优化有哪些手段
- 9.说说你对fiber架构的理解?解决的什么问题?
- 10.如何避免ajax数据请求重新获取
- 11.短轮询、长轮询和 WebSocket 间的区别
- 短轮询和长轮询
- WebSocket
- 12.前端跨域的解决方案
- 13.React render方法的原理,在什么时候会触发
- 14.介绍一下 Tree Shaking
- 15.什么是高阶组件?如何使用?用过哪些高阶组件
- 16.React中受控组件和非受控组件
- 17.虚拟DOM和真实DOM的区别
- 18 .React生命周期的过程
- 19.state和props有什么区别?
- 20.React组件通信的流程
- 21.说说你对Redux中间件的理解
- 22.说说react函数组件和类组件的区别
- JavaScript相关
- 1.Js数据类型判断都有哪几种方式?至少说出5种?它们的区别是什么
- 2.for...in循环和for...of循环的区别
- 3.数组常用方法及作用,至少15个
- 4.说说你对事件循环event loop的理解
- 5.说说你对Promise的理解?
- 6.Promise和async/await有什么区别?
- 7.说说什么是闭包,有哪些应用场景?
- 8.说说你对原型和原型链的理解?场景?
- 9.bind、call、apply 区别?
- Vue相关
- 1.说说你对Object.defineProperty()的理解?
- 2.说说你对vue中mixin的理解
- 2.说说你对Vue中生命周期的理解?
- 3.说说你对Vue中生命周期的理解?
- 4.Vue中数据更新视图不更新的原理是什么?
- 5.Vue中data为什么是一个函数不能是对象?
- HTML相关
- 1.说说你对盒子模型的理解?
- 2.说说你对BFC的理解?
React相关
1.说说React生命周期中有哪些坑?为什么要溢出will相关生命周期
getDerivedStateFromProps
容易编写反模式代码,使受控组件和非受控组件区分模糊- componentWillmount 在React中已被标记弃用,不推荐使用,主要原因是因为新的异步架构会导致它被多次调用,所以网络请求以及事件绑定应该放ComponentDidmount中
- componentWillReceiveProps同样被标记弃用,被
getDerivedStateFromProps
所取代,主要原因是因为性能问题 - shouldcomponentUpdate通过返回true或者false来确定是否需要触发新的渲染,主要用于性能优化
- componentWillupdate同样是由于新的异步渲染机制,而被标记弃用,不推荐使用,原始的逻辑可以结合
getSnapshotBeforeUpdate
与componentDidUpdate
改造使用 - 如果在componentwillUnmount函数中忘记解除事件绑定,取消定时器等清理操作容易引发Bug
- 如果没有添加错误处理,当渲染发生异常时,用户将会看到一个无法操作的白屏
2. 说说Real diff算法是怎么运作的,从tree层到component层到element层分别讲解?
-
Diff算法是虚拟dom的一个必然结果,它是通过新旧dom的对比,将在不更新页面的情况下,将需要的内容局部更新
-
Diff算法遵循深度优先,同层比较的原则
-
可以使用key值,可以更加准确的找到dom节点
react中diff算法主要遵循三个层级的策略
tree层级
component层级
element层级
tree层级不会做任何修改,如果有不一样直接上删除创建
component层从父级往子级查找,如果发现不一致,直接删除创建
element层有key值作比较,如果key值可以复用的话,就会将位置进行移动,如果没有则直接删除创建
3.调和阶段setState干了什么
- 代码中调用setstate函数之后,React会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程
- 经过调和过程,React会以相对较高的方式根据新的状态构建react元素树并且着手重新渲染整个UI界面
- 在react得到元素树之后,react会自动计算出新的树和旧的树存在的差异节点,然后根据差异对界面进行最小化重新渲染
- 在差异计算算法中,React能够相对准确的知道那些位置发生了改变以及应该如何改变,这就保证了按需更新而不是全部重新渲染
4.css3的新特性都有哪些
-
CSS3的新特性大致分为以下六大类
1.CSS3选择器
2.CSS3边框与圆角
3.CSS3背景与渐变
4.CSS3过渡
5.CSS3变换
6.CSS3动画
参考链接
5.说说redux的工作流程
redux是一个第三方状态管理工具,redux遵循三大原则 单一的数据源 state数据是只读的 通过纯函数修改
redux的工作流程是 用户dispatch一个action action执行对应的reduser返回state从而更新store中的state
6.React合成事件的原理,有什么好处和优势?
react并不是将click事件绑定在该div的真实dom上,而是在document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装并交由真正的处理函数运行
好处:
浏览器兼容实现更好的跨平台
顶层事件代理机制:保证冒泡一致性,可以跨浏览器操作。讲不通平台事件模拟成合成事件
避免垃圾回收:
React引入事件池,在事件池中获取或释放事件对象
React事件对象不会被释放掉,而是存入一个数组中,当事件触发,就从这个数组中弹出,避免频繁的创建和销毁
方便事件统一管理和事务机制
7.为什么react元素有一个$$type属性?
目的是为了防止xss攻击,因为synbol无法被序列化,所以react可以通过有没有 t y p e 属性来判断出当前的 e l e m e n t 对象是从数据库来的还是自己生成的,如果没有 type属性来判断出当前的element对象是从数据库来的还是自己生成的,如果没有 type属性来判断出当前的element对象是从数据库来的还是自己生成的,如果没有type属性react会拒绝处理该元素
8.react的性能优化有哪些手段
- 使用纯组件
- 使用React.memo进行组件记忆对于相同的输入不重复执行
- 如果是类组件,使用shouldcomponentUpdate生命周期事件
- 路由懒加载
- 使用React Fragments避免额外标记
- 不要使用内联函数定义
- 避免在willxxx系列的生命周期中进行异步请求,操作dom等
- 如果是类组件,事件函数在
Constructor
中绑定bind改变this指向 - 避免使用内联样式属性
- 优化React中的条件渲染
- 不要在render方法中导出数据
- 渲染列表时加key
- 在函数组件中使用useCallback和useMemo来进行组件优化,依赖没有变化的话,不重复执行
- 类组件中使用
immutable
对象
9.说说你对fiber架构的理解?解决的什么问题?
解决的问题:
JavaScript引擎和页面渲染引擎两个线程是互斥的,当其中一个线程执行时,另一个线程只能挂起等待;如果JavaScript线程长时间的占用了主线程,那么渲染层面的更性就不得不长时间的等待,界面长时间不更新,会导致页面响应度差,用户可能会觉得卡顿
理解:
react Fiber是对react做出的一个重大改变与优化,是对React核心算法的一次重新实现
主要做了:
- 为每个增加了优先级,优先级高的任务可以中断优先级低的任务,然后在重新执行优先级低的任务
10.如何避免ajax数据请求重新获取
-
UI层面的拦截
当用户点击完按钮后,就立即禁用按钮,并开启等待动画,如果收到服务器的成功响应返回后,在隐藏动画,一定要设置超时,
-
JS层面的封锁
-
暴力点击
如果用户暴力点击按钮,我们可以通过防抖函数来解决
-
多个tab页的快速切换
如果使用第三方的请求库的话,比如axios,我们可以为我们的请求创建一个cancel token ,在每个请求设置一个token,在页面切换, 或者组件销毁前,只需要通过source.cancel取消就好了,其实原理还是通过xhr的abort方法实现
-
[参考链接]((78条消息) 如何避免ajax重复请求?_避免重复请求_傲娇的单身狗的博客-CSDN博客)
11.短轮询、长轮询和 WebSocket 间的区别
短连接和长连接
短连接:
- http协议底层基于socket的tcp协议,每次通信都会新建一个TCP连接,即每次请求和响应过程都经历”三次握手-四次挥手“
- 优点:方便管理
- 缺点:频繁的建立和销毁连接占用资源
长连接:
- 客户端和服务端之间只有一条TCP通信连接,以后所有的请求都使用这条连接,也称为持久连接。
- 优点:多次请求-响应基于一条连接,避免资源浪费。
- 缺点:客户端的数量增加,服务端承受的压力增大。对每个请求仍然要单独发header,Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。
总结:
- 长短连接指的是客户端和服务端建立和保持TCP连接的机制。
- 不论是短连接还是长连接,都是客户端主动向服务端发请求,才能获悉数据,服务端是无法主动给客户端推送信息的。
- 服务端主动给客户端推送消息最简单的方式是采用轮询,即客户端每隔一段时间就向服务端发出一个询问,获取服务端最新的消息。最典型的应用就是聊天室。
短轮询和长轮询
短轮询:
- 浏览器每隔一段时间向服务端发送http请求,服务器端在收到请求后,不论是否有数据更新,都直接进行响应。这种方式实现的即时通信,本质上还是浏览器发送请求,服务器接受请求的一个过程,通过让客户端不断的进行请求,使得客户端能够模拟实时地收到服务器端的数据的变化。
- 优点:比较简单,易于理解;
- 缺点:由于需要不断的建立 http 连接,严重浪费了服务器端和客户端的资源。当用户增加时,服务器端的压力就会变大,这是很不合理的。
长轮询:
-
首先由客户端向服务器发起请求,当服务器收到客户端发来的请求后,服务器端不会直接进行响应,而是先将 这个请求挂起,然后判断服务器端数据是否有更新。
如果有更新,则进行响应,如果一直没有数据,则到达一定的时间限制才返回。客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
-
优点:「明显减少了很多不必要的 http 请求次数」,相比之下节约了资源。
-
缺点:实现复杂,且连接挂起也会导致资源的浪费。
总结:
- 短轮询和长轮询指的是客户端请求服务端,服务端给予响应的方式。
- 轮询的方式可以解决服务端主动向客户端推送消息的需求,但是轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
- 为了更好的解决这个问题,于是出现了WebSocket
WebSocket
简介:
- WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。
- 服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
- 可以发送文本,也可以发送二进制数据。
- 协议标识符是
ws
(如果加密,则为wss
),服务器网址就是 URL。
websocket:websocket是长连接,是一个真的全双工,第一次tcp链路建立以后,后续所有数据双方都主动发送,不需要发送请求头,与传统的 http 协议不同,该协议允许由服务器主动的向客户端推送信息。与HTTP长连接不同,websocket可以更灵活的控制连接关闭的时机,而不是HTTP协议的Keep-Alive一到,服务端立马就关闭(这样很不人性化)。
优点:
- 建立在 TCP 协议之上,服务器端的实现比较容易。
- 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
- 数据格式比较轻量,性能开销小,通信高效。
- 没有同源限制,客户端可以与任意服务器通信。
缺点:
-
使用 WebSocket 协议的缺点是在服务器端的配置比较复杂。
[参考链接]([(78条消息) 长/短 链接/轮询 和websocket_潇潇说测试的博客-CSDN博客](https://blog.csdn.net/NHB456789/article/details/130440124?ops_request_misc=&request_id=a587b8a5a185498d88091eba2a2990cf&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2allkoosearch~default-1-130440124-null-null.142v88insert_down28v1,239v2insert_chatgpt&utm_term=短轮询、长轮询和 WebSocket 间的区别&spm=1018.2226.3001.4187))
12.前端跨域的解决方案
什么是跨域
在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服ajax只能同源使用的限制
什么事同源策略
同源策略是一种约定,由NEtscape公司1995年引入浏览器,它是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,浏览器很容易受到xss csfr等攻击。所谓同源是指
协议+域名+端口三者相同 即使两个不同的域名指向同一个ip地址 也非同源
同源策略限制以下几种行为:
Cookie、LocalStorage 和 IndexDB 无法读取
DOM和JS对象无法获得
AJAX 请求不能发送
跨域解决方案
- JSONP跨域
- 跨域资源共享(CORS)
- nginx代理跨域
- nodejs中间件代理跨域
- docoment.domain+iframe跨域
- location.hash+iframe跨域
- window.name+iframe跨域
- postMessage跨域
- WebSocket协议跨域
13.React render方法的原理,在什么时候会触发
React中render方法在函数组件中指的是整个函数
在类组件中render方法指的就是render方法
触发时机:
函数组件和类组件在初次渲染时会触发render方法
类组件在调用setState时会触发render方法
函数组件通过useState hook更改状态时会触发render方法
14.介绍一下 Tree Shaking
Tree-shaking
是一个用于优化 JavaScript
应用程序的技术,它可以在打包过程中去除无用的代码,从而减小最终打包后的文件大小。
Tree-shaking
的基本原理是通过静态分析的方式识别和删除不被使用的代码。在 JavaScript
应用程序中,往往会引入许多库和模块,但是并不是所有的代码都会被使用。Tree-shaking
可以自动地分析和删除这些无用的代码,从而减小打包后的文件大小
15.什么是高阶组件?如何使用?用过哪些高阶组件
高阶组件:
官方解释:高阶组件是React中用于复用组件逻辑的一种高级技巧,高阶组件
自身不是React API的一部分 他是基于react的组合特性形成的设计模式
高阶组件(HOC
)就是一个函数, 且该函数接受一个组件作为参数, 并返回一个新的组件, 它只是一种组件的设计模式, 这种设计模式是由 react
自身的组合性质必然产生的。我们将它们称为纯组件, 因为它们可以接受任何动态提供的子组件, 但它们不会修改或复制其输入组件中的任何行为
react提供的高阶组件有:
react-router-dom 5版本的withRoute
redux-react Provider connect
16.React中受控组件和非受控组件
受控组件:受控组件就是我们可以通过 setstate控制组件的值
非受控组: 非受控组件不会受到setstate的控制
17.虚拟DOM和真实DOM的区别
1. 虚拟dom不会进行排版和重绘
- 虚拟dom进行频繁的修改,然后一次性比较并修改真实dom,最后并在真实dom中进行排版和重绘,减少过多dom节点的排版和重绘损耗
- 真实dom的频繁排版和重绘的效率的相当低的
- 虚拟dom有效降低大面积 真实dom节点的排版和重绘,因为最终于真实dom比较差异,可以只渲染局部
18 .React生命周期的过程
react生命周期分为三个阶段:挂载阶段 更新阶段 卸载阶段
react16版本之前的生命周期为:
挂载阶段:constructor componentWillMount render componentDidMount
更新阶段:componentWillReceiveProps shouldComponentUpdate componentWillUpdate componentDidUpdate
卸载阶段:componentWillUnmount
react16之后的生命周期为:
挂载阶段:constructor getDerivedStateFromProps render 更新dom和refs componentDidMount
更新阶段:getDerivedStateFromProps shouldComponentUpdate render getSnapshotBeforeUpdate 更新dom和refs componentDidUpdate
卸载阶段:componentWillUnmount
19.state和props有什么区别?
react中props和state的相同点和不同点:
props不可以直接修改,state可以在组内部直接修改
可以从父组件中修改props,但是不可以在父组件中修改子组件的state
相同点:
prop和state都是导出HTML原始数据
props和state都是确定性的,
props和state都会触发渲染更新
props和state都是js对象 通过typeof判断 都是object
可以从父组件得到初始值props和state的初始值
20.React组件通信的流程
react中的组件通信的方式:
父子组件的通信:
父组件与子组件通信可以通过props实现 在父组件中给子组件绑定自定义属性 子组件通过props进行访问
子组件父组件通信:
在父组件中定义一个函数通过props传递给子组件 子组件通过props调用这个函数将父组件用到的数据作为参数进行传递
兄弟组件的通信将父组件作为媒介通过props进行通信
跨层级通信:
Context状态树进行通信
redux
21.说说你对Redux中间件的理解
redux中间件:中间件(Middleware)是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的 常用的中间件:redux-thunk redux-logger
22.说说react函数组件和类组件的区别
类组件:类组件,顾名思义也就是通过Es6类的编写形式去编写组件该类必须继承React.Component类组件是存在状态管理的类组件存在生命周期类组件中存在this指向函数组件:函数组件以函数的形式编写的组件称为函数组件函数组件没有生命周期 可以通过useEffect hook模拟生命周期函数组件没有状态管理 可以使用useState hook管理状态函数组件没有this
JavaScript相关
1.Js数据类型判断都有哪几种方式?至少说出5种?它们的区别是什么
1. typeof
判断
typeof
返回的类型都是字符串形式
2. Constructor
实例constructor
属性指向构造函数本身
constructor
判断方法跟instanceof
相似,但是constructor
检测Object
与instanceof
不一样,constructor
还可以处理基本数据类型的检测,不仅仅是对象类型
3. Instanceof
instanceof
可以判类型是否是实例的构造函数
instanceof
后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。
4. Object.prototype.toString.call()
判断类型的原型对象是否在某个对象的原型链上
5. 通过object
原型上的方法判断
比如array.isArray()
来判断是不是一个数组
6. ===(严格运算符)
通常出现在我们的条件判断中,用来判断数据类型的话就会非常的有局限性,比如判断一个变量是否为空,变量是否为数据等
2.for…in循环和for…of循环的区别
for…in循环 :只能获取对象的键名,不能不去键值
for…in循环有几个缺点:
-
数组的键名是数字,但是for…in循环会以字符串作为键名
-
for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型连上键
-
某些情况下for…in循环会以任意循序遍历键名
for…i循环主要是为遍历对象而设计的,不适用于遍历数组
for…of循环:允许遍历获取键值
- 有着同for…in循环一样的简介语法,但是没有for…in那些缺点
- 不同于forEach方法,它可以结合break continue和return配合使用
- 提供了遍历所有数据结构的统一操作接口
3.数组常用方法及作用,至少15个
-
Array.length:
返回或设置一个数组中的元素个数 Array.from() :
对伪数组或可迭代对象(包括arguments
,Array
,Map
,Set
,String
…)转换成数组对象Array.isArray():
用于确定传递的值是否是一个Array
concat():
方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。every(callback):
方法测试数组的所有元素是否都通过了指定函数的测试filter():
创建一个新数组, 其包含通过所提供函数实现的测试的所有元素find():
返回数组中满足提供的测试函数的第一个元素的值forEach():
方法对数组的每个元素执行一次提供的函数includes():
用来判断一个数组是否包含一个指定的值,如果是,酌情返回true
或false
indexOf():
返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1join():
将数组(或一个类数组对象)的所有元素连接到一个字符串中lastIndexOf():
返回指定元素(也即有效的JavaScript
值或变量)在数组中的最后一个的索引,如果 不存在则返回 -1。从数组的后面向前查找map():
创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果pop():
从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度push():
将一个或多个元素添加到数组的末尾reduce():
累加器和数组中的每个元素(从左到右)应用一个函数shift():
从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度slice():
返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象some():
测试数组中的某些元素是否通过由提供的函数实现的测试。sort():
当的位置对数组的元素进行排序,并返回数组。splice():
通过删除现有元素和/或添加新元素来更改一个数组的内容toString():
返回一个字符串,表示指定的数组及其元素unshift():
将一个或多个元素添加到数组的开头,并返回新数组的长度toLocaleString():
返回一个字符串表示数组中的元素。数组中的元素将使用各自的toLocaleString
方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 “,”)隔开
4.说说你对事件循环event loop的理解
任务在主线程不断进栈出栈的一个循环过程,任务会再将要执行时进入主线程,在执行完毕后会退出主线程
JavaScript是一门单线程的语言,意味着同一时间内只能做一件事情
但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环
在JavaScript所有的任务都可以分为:
同步任务:立即执行的任务,同步任务一般会直接进入主线程中执行
异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等
异步任务还可以细分为微任务和宏任务
微任务一个需要异步执行的函数,执行时机是在主函数执行结束之后,当前宏任务结束之前宏任务的时间颗粒比较大,执行的时间是不能精确控制的,对一些高实时性的需求就不太符合
5.说说你对Promise的理解?
promise 是最早由社区提出和实现的一种解决一步编程的方案,比其他传统的解决方案(回调函数和事件)更合理更强大
promise的两个特点:
promise对象的状态不会受到外界影响
1)pending 初始状态
2)fulfilled 成功状态
3)rejected 失败状态
promise有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他操作都无法改变这个状态
promise的状态一旦发生改变,就不会在改变 任何时候都可以得到这个结果 状态不可逆只能由 pending变成fulfilled或者由pending变成rejected
Promise的缺点:
无法取消promise一旦新建就会立即执行 无法中途取消
如果不设置回调函数,Promise内部抛出的错误 不会放映到外部
当处于pending状态时,无法得知目前进展到哪一个阶段 ,
6.Promise和async/await有什么区别?
1. Promise是一种在JavaScript中处理异步操作的方式,他被设计用来处理一个异步操作
并在操作完成后返回结果,Promise有三种状态 pending(进行中)、fulfilled(已完成)和rejected(已失败)它们分别表示Promise操作的不同阶段 Promise可以使用then()和catch()方法来处理fulfilled和rejected状态。
async/await 是es7提供的一种异步编程方式。它是一种建立在Promise之上的语法糖,可以让异步代码看起来更像同步代码 async关键字用于定义一个异步函数,然后可以在这个函数中使用 await关键字来等待一个Promise完成 async/await可以简化一些异步操作的代码 使得它们更容易去理解和维护。
区别:
Promise和async/await的区别在于 Promise是一种较早的异步编程方式,而async/await是es7新引入的异步编程方式 romise使用了回调函数来处理异步操作,从而在代码中形成了“回调地狱”。而async/await通过一种更加直观的方式来管理异步操作,使得代码更容易理解和维护。
参考链接地址:
参考链接地址:
7.说说什么是闭包,有哪些应用场景?
1. 一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)
也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域
在 JavaScript
中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁
- 创建私有变量
- 延长变量的生命周期
8.说说你对原型和原型链的理解?场景?
原型:
JavaScript
常被描述为一种基于原型的语言——每个对象拥有一个原型对象
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾
准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype
属性上,而非实例对象本身
原型链:
原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法
在对象实例和它的构造器之间建立一个链接(它是__proto__
属性,是从构造函数的prototype
属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法
9.bind、call、apply 区别?
call、apply、bind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向
区别:apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入改变this指向后原函数会立即执行,且此方法只能临时改变this指向一次call方法的以一个参数也是this的指向,后面传入的死一个参数列表跟apply一样,改变thiis指向后会立即执行,且此方法只是临时改变this指向一次bind方法和call很相似,第一个参数也是this的指向,后面传入的也是一个参数列表可以分多次传入,改变this指向后不会立即执行,而是返回一个永久改变this指向的函数
Vue相关
1.说说你对Object.defineProperty()的理解?
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
该方法接受三个参数
- 第一个参数是
obj
:要定义属性的对象, - 第二个参数是
prop
:要定义或修改的属性的名称或Symbol
, - 第三个参数是
descriptor
:要定义或修改的属性描述符
函数的第三个参数descriptor
所表示的属性描述符有两种形式:数据描述符和存取描述符。 - 数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。
- 存取描述符是由
getter
函数和setter
函数所描述的属性。
一个描述符只能是这两者其中之一;不能同时是两者。
这两种同时拥有下列两种键值:
configurable
: 是否可以删除目标属性或是否可以再次修改属性的特性(writable
,configurable
,enumerable
)。设置为true
可以被删除或可以重新设置特性;设置为false
,不能被可以被删除或不可以重新设置特性。默认为false
。
enumerable
: 当且仅当该属性的enumerable
键值为true
时,该属性才会出现在对象的枚举属性中。默认为false
。
2.说说你对vue中mixin的理解
mixin是一种类,在vue中就是js文件,主要的作用是作为功能模块引用。因为在项目中,可能不同组件会有相同的功能,比如控制元素的显示和隐藏,如果他们的变量和规则也完全相同的话,就可以把这个功能单独提取出来,放在mixin.js中,再引入,就可以实现一样的功能了。引入的方法也分为全局混入和局部混入,局部混入就是在每个组件中引入,全局混入就是在main.js中通过Vue.mixin()引入。[参考链接]((78条消息) [前端知识之Vue]对vue中mixin的理解_前端mixin_饭啊饭°的博客-CSDN博客)
2.说说你对Vue中生命周期的理解?
vue中的生命周期:
Vue生命周期总共可以分为8个阶段:创建前后, 载入前后,更新前后,销毁前销毁后,以及一些特殊场景的生命周期
生命周期 | 描述 |
---|---|
beforeCreate | 组件实例被创建之初 |
created | 组件实例已经完全创建 |
beforeMount | 组件挂载之前 |
mounted | 组件挂载到实例上去之后 |
beforeUpdate | 组件数据发生变化,更新之前 |
updated | 组件数据更新之后 |
beforeDestroy | 组件实例销毁之前 |
destroyed | 组件实例销毁之后 |
activated | keep-alive 缓存的组件激活时 |
deactivated | keep-alive 缓存的组件停用时调用 |
errorCaptured | 捕获一个来自子孙组件的错误时被调用 |
3.说说你对Vue中生命周期的理解?
Vue2的响应式原理的核心是Object.**defindeProperty** 进行数据劫持,然后利用get和set方法进行数据的获取和设置这是data中的属性都会被添加到get和set中当读取data中的属性的时候自动调用get方法,当修改数据时或者数据发生改变时自动调用 set方法去侦听检测数据的变化同时会通知观察着Wacher 观察者Wacher自动触发render当前组件子组件不会重新渲染生成新的虚拟dom树VUe的框架会遍历对新旧DOm树上面的每个节点的差异并记录下来最后加载操作将所有记录下来的节点局部修改到真实的dom树上
4.Vue中数据更新视图不更新的原理是什么?
vue中数据更新视图不更的情况:
我们动态的修改数组,执行添加删除等操作,或者动态修改对象
由于vue是双向数据绑定的,我们在更新数据时,数据更新了视图没有发生变化
解决的方法通过$set
5.Vue中data为什么是一个函数不能是对象?
vue实例中data可以使一个函数也可以是一个对象
但是vue组件中data必须是一一个函数
vue中的组件是为了复用的如果vue组件中data是一个对象由于对象是引用数据类型
我们在复用组件时会造成数据的混乱,而data是一个函数每一次返回一个对象,
对象的内存地址是不一样的,对data中的数据进行了隔离
HTML相关
1.说说你对盒子模型的理解?
盒子模型分为:标准盒子模型和怪异盒子模型
编写html文档是默认的盒子模型是标准盒子模型
概念:
标准盒子模型:标准盒子模型采用W3C标准,盒子的content内容部分有高度和宽度决定 添加外边距或者外边框后宽高都会响应增长
怪异盒子模型:怪异盒子模型也称为IE盒子模型,是IE浏览器设计元素时遵循的规则,怪异盒模型的宽高在div盒子初次设置就已经规定,添加padding或者border会从中减少content内容的占据区域 来为padding和border制造空间 宽高不会响应增长
计算方法:
-
标准盒模型的内容计算:content=width+height
盒子的总宽度=width+padding(左右)+margin(左右)+border(左右)
总宽度等于所有的附加值偏移值的总和
-
怪异盒子模型的内容计算:content=width+height+padding+border
盒子的中宽度=windth+margin(左右)此时的width宽度已经包含了padding和border的值
2.说说你对BFC的理解?
、BFC 块级格式化上下文:里面的元素不会影响外面的元素。
- 一个BFC区域只包含其子元素,不包括子元素的子元素
- BFC区域需要一定的条件:该元素设置浮动、定位、弹性布局等
- 不同的BFC区域之间是相互独立的