前端基础知识与常见面试题(十三)

异步事件循环:
——宏任务:(script是宏任务)
1.新程序或子程序被执行
2.事件的回调函数
3.setTimeout()和setInterval()
——微任务:
1.Promise.then().catch().finally()
2.MutationObserver
3.Object.observe
宏任务—>微任务—>渲染—>宏任务
         ——事件循环——
宏任务—>微任务—>渲染—>宏任务
         ——事件循环——
————————————————————————————
forEach()如何跳出循环
try{
arr.forEach((item,index,arr)=>{
if(index===2) throw 'error
})
}catch(err){
console.log((err))
//console.error(err)
}
————————————————————————————
正常try,catch只能捕捉同步,如果想要捕捉异步操作需要结合async和await,例如:
async function fn1(){
let n=Promise.reject(666);
try{
         await n
         console.log(n)
    }catch(err){
         console.error('err',err)
    }
}
————————————————————————————
Promise
例一:
const isPregnant=false;
const promise = new Promise((resolve,reject)=>{
if(isPregnant){
resolve('孩子他爹')
}else{
reject('老公')
}
});
promise
.then(name=>{
console.log(`男人成为了${name}`)//男人成为了孩子他爹
})
.catch(name=>{
console.log(`男人成为了${name}`)//男人成为了老公
})
.finally(()=>{
console.log(`男人和女人最终结婚了!`)//男人和女人最终结婚了!
});
例二:
const imgAddress="https://wx1.sinaimg.cn/mw2000/0088k7xjly1h64yzr16bnj30qo1c1whk.jpg"
const imgPromise=(url)=>{
return new Promise((resolve,reject)=>{
const img=new Image();
img.src=url;
img.οnlοad=()=>{
resolve(img)
}
img.οnerrοr=()=>{
reject(new Error('图片有误'))
}
})
}
 imgPromise(imgAddress)
    .then(img=>{
document.body.appendChild(img)
})
.catch(err=>{
document.body.innerHTML=err
})
————————————————————————————
面试题:Web项目中实现AJAX效果,有哪些技术可用?
① XHR:W3C标准技术,兼容性好,但麻烦且基于回调
② jQuery.ajax():第三方库,兼容性好,基于回调
③ axios:第三方模块,兼容性好,基于Promise —— 可用于基于浏览器的项目或Node.js项目
④ wx.request() / uni.request():专用于小程序或uni-app项目
⑤ fetch:W3C标准技术,用于取代XHR,基于Promise,功能强大,老IE不支持 —— 可用于基于浏览器的项目或脱离浏览器的项目(例如: RN)
————————————————————————————
React中的“父子组件间传参”
父亲给儿子传递数据 ——Props Down:
//Parent.js
function Parent(){
  let [age] = useState(20)
 return  <Child  count={age}/>
}
//Child.js
function Child( props ){
   clog( props.count ) 
}
儿子给父亲传递数据 ——Props Up:
//Parent.js
function Parent(){
function showPage( n ){
     clg('父组件的方法想使用子组件的数据:', n)
  }
 return  <Child  f1={showPage}/>//父组件把自己的方法传递给子组件
}
//Child.js
function Child(props ){
  let pno = 3
props.f1( pno ) //子组件通过自己的属性调用了父组件的方法,实参就是子组件的数据
}
总结:
1.父子组件通信:props+函数
2.爷孙组件通信:两层父子通信或者使用Context.Provider和Context.Consumer
3.任意组件通信:消息订阅-发布、集中式管理(Redux、Mobx)
————————————————————————————
数据分为基本数据类型和引用数据类型。
基本数据类型:数据直接存储在栈中;
引用数据类型:存储在栈中的是对象的引用地址,真实的对象数据存放在堆内存中。
浅拷贝:对于基本数据类型:直接复制数据值;对于引用数据类型:只是复制了对象的引用地址,新旧对象指向同一个内存地址,修改其中一个对象的值,另一个对象的值也随之改变。
深拷贝:对于基本数据类型:直接复制数据值;对于引用数据类型:开辟新的内存空间,在新的内存空间里复制一个一模一样的对象,新老对象不共享内存,修改其中一个对象的值,不会影响另一个对象。
深拷贝相比于浅拷贝速度较慢并且花销较大。
对象数组等引用数据如何实现深拷贝?
先把其转换成JSON字符串,再转换成JS对象
例:const list=[{henan:'加油'}];
const listCopy=JSON.parse(JSON.stringify(list));
listCopy[0].henan='挺住';
console.log(list);
console.log(listCopy);
————————————————————————————
如何面向对象:封装,继承,多态
————————————————————————————
HTTP的强制缓存与协商缓存
(1)强缓存
使用强缓存策略时,如果缓存资源有效,则直接使用缓存资源,不必再向服务器发起请求。
强缓存策略可以通过两种方式来设置,分别是 http 头信息中的 Expires 属性和 Cache-Control 属性。(Cache-Control:max-age=31536000)
(2)协商缓存
如果命中强制缓存,我们无需发起新的请求,直接使用缓存内容,如果没有命中强制缓存,如果设置了协商缓存,这个时候协商缓存就会发挥作用了。
上面已经说到了,命中协商缓存的条件有两个:
● max-age=xxx 过期了
● 值为no-cache
使用协商缓存策略时,会先向服务器发送一个请求,如果资源没有发生修改,则返回一个 304 状态,让浏览器使用本地的缓存副本。如果资源发生了修改,则返回修改后的资源。
协商缓存也可以通过两种方式来设置,分别是 http 头信息中的 Etag 和 Last-Modified 属性。
总结:
强缓存策略和协商缓存策略在缓存命中时都会直接使用本地的缓存副本,区别只在于协商缓存会向服务器发送一次请求。它们缓存不命中时,都会向服务器发送请求来获取资源。在实际的缓存机制中,强缓存策略和协商缓存策略是一起合作使用的。浏览器首先会根据请求的信息判断,强缓存是否命中,如果命中则直接使用资源。如果不命中则根据头信息向服务器发起请求,使用协商缓存,如果协商缓存命中的话,则服务器不返回资源,浏览器直接使用本地资源的副本,如果协商缓存不命中,则服务器返回最新的资源给浏览器。
为什么需要浏览器缓存?
对于浏览器的缓存,主要针对的是前端的静态资源,最好的效果就是,在发起请求之后,拉取相应的静态资源,并保存在本地。如果服务器的静态资源没有更新,那么在下次请求的时候,就直接从本地读取即可,如果服务器的静态资源已经更新,那么我们再次请求的时候,就到服务器拉取新的资源,并保存在本地。这样就大大的减少了请求的次数,提高了网站的性能。这就要用到浏览器的缓存策略了
所谓的浏览器缓存指的是浏览器将用户请求过的静态资源,存储到电脑本地磁盘中,当浏览器再次访问时,就可以直接从本地加载,不需要再去服务端请求了。
使用浏览器缓存,有以下优点:
● 减少了服务器的负担,提高了网站的性能
● 加快了客户端网页的加载速度
● 减少了多余网络数据传输
————————————————————————————
react专题
请说一下你对React的理解?(VUE是渐进式JavaScript 框架)
react是什么?
用于构建用户界面的 JavaScript 库
react能干什么?
可以通过组件化的方式构建,构建快速响应的大型Web应用程序
请说一下你对虚拟DOM的理解?
React.createElement函数所返回的就是一个虚拟DOM
虚拟DOM就是一个描述真实DOM的纯JS对象
————————————————————————————
虚拟DOM优缺点:
优点:(跨平台;差异化更新;处理浏览器兼容性问题)
1.处理了浏览器兼容性问题,避免用户操作虚拟DOM,那么又麻烦又容易出错
2.内容经过XSS处理,可以防范XSS攻击
3.容易实现跨平台开发Android,IOS,VR应用
4.更新的时候可以实现差异化更新,减少更新DOM的操作
缺点:
1.虚拟DOM需要消耗额外的内存
2.首次渲染并不一定会更快(在初次渲染的时候其实并不快,在更新的时候,更新的元素内容比较少,它可以实现精准定点更新,不需要把全部的DOM元素删除重添加)
———————————————————————————
源码如何判断是类组件还是函数组件:
isReactComponent(有isReactComponent为类组件,没有为函数组件)
———————————————————————————
什么是JSX?
JSX是一种Javascript的语法扩展,可以很好的描述UI的架构。是React.createElement的语法糖。浏览器不能直接解析JSX文件,需要通过Bable进行转译成js。
————————————————————————————
讲一下虚拟Dom?
虚拟Dom:虚拟Dom是描述真实Dom的js对象。
特点:(1)处理了浏览器兼容性问题,避免用户操作真实DOM,不容易出错。
(2)内容经过了XSS处理,可以防范XSS攻击。
(3)可以实现跨平台开发。
(4)在更新的时候,比较两棵虚拟DOM树的差异,差异化更新。
延伸题:
什么是diff算法?diff算法,就是用来找出两段文本之间的差异的一种算法。
vdom为什么用diff算法?
由于DOM操作是非常昂贵的,就可以通过diff算法来减少DOM操作。
vdom比真实dom快?
回答:不一定。
在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。
无效、无意义的diff是需要浪费性能的,因此有些场景不如直接操作原生DOM性能好。
———————————————————————————
类组件和函数组件之间的区别是什么?
相同点:它们都可以接收属性并且返回React元素。
不同点:
(1)类组件需要创建实例,是基于面向对象的方式编程,函数组件不需要创建实例,接收输入,返回输出,是基于函数编程的思想。
(2)类组件需要创建并且保持实例,会占用一定的内存,函数组件不需要创建实例,可以节约内存占用。
(3)类组件有完整的生命周期,函数组件没有生命周期(现在通过useEffect实现类似生命周期的功能)
(4)类组件通过shouldComponent和pureComponent跳过更新,而函数组件可以通过React.memo跳过更新。
(5)类组件服用逻辑一般用HOC,函数组件可以自定义Hook。
延伸题:源码如何区分函数组件与类组件?\n通过Component.prototype.isReactComponent属性来判断。
——————————————————————————
hooks出现的意义?
Hook 是 React 16.8 的新增特性。
它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hooks 优势:
(1)函数组件无 this 问题
(2)自定义 Hook 方便复用状态逻辑
(3)副作用的关注点分离
————————————————————————————
setState 同步还是异步?(比较常问)
(1)React生命周期中以及事件处理中,为异步。
(2)原生方法(setTimeout,setInnerval,addEventListener )中是同步 。
原理:setState本身并不是异步,只是因为react的性能优化机制体现为异步。在react的生命周期函数或者作用域下为异步,在原生的环境下为同步。 因为每次调用setState都会触发更新,异步操作是为了提高性能,将多个状态合并一起更新,减少re-render调用。
性能优化机制:在 React 的 setState 函数实现中,会根据一个变量isBatchingUpdates判断是直接更新 this.state 还是放到队列中。isBatchingUpdates 默认是 false,React 在调用事件处理函数之前会将isBatchingUpdates改为true,造成的后果就是由 React 控制的事件处理过程 setState 不会同步更新 this.state。而原生方法不会被React控制。
————————————————————————————
React-router路由模式?
hash模式(HashRouter):通过监听 hashchange 事件, 在回调里拿到 window.location.hash 的值。 hash 就是指 url 尾巴后的 # 号以及后面的字符。
hash模式原理:
使用window.location.hash属性及窗口的onhashchange事件,可以实现监听浏览器地址hash值变化,执行相应的js切换网页。 hash指的是地址中#号以及后面的字符,也称为散列值。
history模式(BrowserRouter): 利用history API实现url地址改变,网页内容改变。
history模式原理:
window.history 属性指向 History 对象,它表示当前窗口的浏览历史。 History 对象保存了当前窗口访问过的所有页面网址
————————————————————————————
React Hook:useEffect与函数式组件的生命周期
(function式组件)    
useEffect( ()=>{
//生命周期方法1=组件挂载+任意数据改变
} )
componentDidMount+ componentDidUpdate(class式组件)
·······
useEffect( ()=>{
//生命周期方法2=组件挂载+依赖的数据改变
}, [count, age] )    
componentDidMount+ componentDidUpdate
·······
useEffect( ()=>{
//生命周期方法3=组件挂载
}, [] )    
componentDidMount
·········
useEffect( ()=>{
return ()=>{
//生命周期方法4=任意数据改变+组件卸载
    }
} )    
componentDidUpdate+componentWillUnmount
·········
useEffect( ()=>{
return ()=>{
//生命周期方法5=依赖的数据改变+组件卸载
    }
}, [count, age])    
componentDidUpdate+componentWillUnmount
············
useEffect( ()=>{
return ()=>{
//生命周期方法6=组件卸载
    }
}, [])    
componentWillUnmount
——————————————————————————
redux的工作流程?
核心概念:
Store:保存数据的地方,你可以把它看成一个容器,整个应用只能有一个Store
State:Store对象包含所有数据,如果想得到某个时点的数据,就要对Store生成快照,这种时点的数据集合,就叫做State。
Action:State的变化,会导致View的变化。但是,用户接触不到State,只能接触到view。所以,State的变化必须由View导致的。Action就是View发出的通知,表示State应该要发生变化了。
Action Creator:View要发送多少种消息,就会有多少种Action。如果都手写,会很麻烦,所以我们定义一个函数来生成Action,这个函数就叫Action Creator。
Reducer:Store收到Action以后,必须给出一个新的State,这样View才会发生变化。这种State的计算过程就叫做Reducer。Reducer是一个函数,他接受Action和当前State作为参数,返回一个新的State。
dispatch:是Vie发出Action的唯一方法。
工作流程:
(1)首先,用户(通过View)发出Action,发出方式就用到了dispatch方法。
(2)然后,Store自动调用Reducer,并且传入两个参数:当前State和收到的Action,Reducer会返回新的State。
(3)State一旦有变化,Store就回调用监听函数,来更新View。
———————————————————————————
你对Time Silce(时间分片)的理解?
React在渲染(render)的时候,不会阻塞现在的线程
如果你的设备足够快,你会感觉渲染是同步的\n如果你得设备非常慢,你会感觉还算是灵敏的
虽然异步渲染,但是你将会看到完整的渲染,而不是一个组件一行行的渲染出来
同样书写组件的方式\n也就是说,这事React背后在做的事情,对于我们开发者来说,是透明的,具体是什么样的效果呢?
例如,由三个图表,有一个输入框以及上面的三种模式
这个组件非常的巨大,而且在输入框每次输入东西的时候,就回进去一直在渲染。
同步模式:
在同步模式下,我们都知道,我们没输入一个字符,React就开始渲染,当React渲染一颗巨大的树的时候,是非常卡的。所以才会有shouldUpdate的出现。
Debounced模式:
Debounced模式简单的来说,就是延迟渲染,比如,当你输入完以后,在开始渲染所有的变化。这么做的坏处就是,至少不会阻塞用户的输入了,但是依然由非常严重的卡顿。
异步模式:
一部渲染模式就是不阻塞当前线程,继续跑。时间分片正是基于可随时打断、重启Fiber架构,可打断当前任务,优先处理紧急且重要的任务,保证页面的流程运行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值