前言
这周一随便找了家公司面试了一下,通话质量那叫一个差呀,我把我听得清的面试题都记录了一下,顺便整理一下答案。
HTML
1、iframe的优缺点
优点:
- iframe可以完整的加载嵌入的页面
- 可以并行加载脚本
- 可以很容易的引入第三方内容 缺点:
- 会阻塞主页面的onload事件进程
- 搜索引擎爬虫不易爬取,不利于SEO
- 和主页面共享连接池,导致页面加载缓慢
TS基础
1、讲一下never,any和unknown分别是什么类型?
any:没有类型校验
unknown:未知类型,只有在校验过后才能够操作,如下:
const test = (a: unknown) => {
const str1: string = a; // 不能将类型“unknown”分配给类型“string”
if(typeof a === "string") {
const str2 = a; // ok
}
}
never:永远不可能的类型,一般用于抛出错误异常的function中。
补充一个void类型: 无类型,一般用于返回值为空的函数体。
2、讲一讲const和readonly的区别
- const关键字只能用于字段的声明,而readonly是在定义类或定义构造函数时初始化的属性。
- const必须在声明时就有个初始值,而readonly不需要
3、定义interface时!号和?的含义
!: 非空属性
?: 可选属性
4、type(类型别名)和interface(接口)的异同
相似点:
- 两者都可以定义对象的类型
- 都可以被继承,甚至可以相互继承
type People1 {
name: string,
age: number
}
interface People2 {
name: string,
age: number
}
// 继承
// interface 继承 type
interface Student1 & People1 { id: string }
// interface 继承 interface
interface Student2 extends People2 { id: string }
// type 继承 type
type Student3 & People1 { id: string }
// type 继承 interface
type Student4 interface People2 { id: string }
不同点:
- type可以定义基本类型
type name = string
- type可以声明联合类型
type Student = {stuNo: number } | { classId : number }
- type 可以声明元组
type Data = [number, string]
- interface可以合并声明,但是type不行
interface Person {name: string}
interface Person {age: number }
// 不会报错,默认合并了声明,但是type这样操作会报错
React
1、请讲讲react 的生命周期
仅适用于class组件的生命周期,虽然现在都用hook,但是面试官还是喜欢考~
先上图:
(1)挂载阶段
-
construcor(),初始化参数,用super继承props和context。
-
componentWillMount(),它代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。
-
render(),第一次渲染
-
componentDidMount(),组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染
-
componentWillUnmount(),组件卸载,在这个阶段你可以清空计时器,移除各类事件监听。至此挂载阶段结束。
(2)更新阶段
- getDerivedStateFromProps(nextProps, prevState)
16.4的新钩子函数,取代了原来的componentWillReceiveProps()。老版本中的componentWillReceiveProps()方法判断前后两个 props 是否相同,如果不同再将新的 props 更新到相应的 state 上去。这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,另一方面也会增加组件的重绘次数。
-
shouldComponentUpdate(),该函数可用于判断组件是否更新,避免不必要的渲染。
-
render(),渲染~
-
getSnapshotBeforeUpdate(prevProps, prevState), 取代了componentWillUpdate()。 这两者的区别在于:
-
在 React 开启异步渲染模式后,在 render 阶段读取到的 DOM 元素状态并不总是和 commit 阶段相同,这就导致在componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
-
getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。
此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。
- componentDidUpdate(prevProps, prevState)
组件更新完毕,可以拿到组件更新前的props和state。处理完相关的操作后还是走到了卸载阶段。
2、组件之间如何通信
父传子: props直接获取
子传父: 函数回调取值
无关联的组件之间通信可以用redux或者useContext和useReducer来实现。
3、如何校验props
我回答的是我们用interface定义一个IProps,去限制props的类型,他不是很满意,问我知不知道propTypes,我不太清楚。事后我问了一下大佬,他认为propTypes其实也差不多,我们的项目因为用了ts所以才没有用propTypes,以下是相关的语法。
import PropTypes from "prop-types"
const Greating = (props) => {
......
}
Greating.propTypes = {
name: PropTypes.string
}
4、你了解react fiber
在 react16 引入 Fiber 架构之前,react 会采用递归对比虚拟DOM树,找出需要变动的节点,然后同步更新它们,这个过程 react 称为reconcilation(协调)。在reconcilation期间,react 会一直占用浏览器资源,会导致用户触发的事件得不到响应。
为了解决这个问题,facebook 团队使用两年多的时间去重构 React 的核心算法,也就是目前我们所知道的Fiber。
简单来说就是在虚拟dom渲染成实际的dom之前,会将虚拟dom转化(reconcile)为fiber树,这个树清晰的记录了父节点、兄弟节点和子节点等相关节点,使得渲染过程可以中断,执行更高优先级的事件,不必每次都重新渲染,大大的提升了性能。
内容要将起来其实好多好多,直接外链两个我觉得不错的文章供大家学习,更加深入理解react fiber
走进 React Fiber 的世界-阿里云开发者社区 (aliyun.com)
阿里三面:灵魂拷问——有react fiber,为什么不需要vue fiber呢? - 掘金 (juejin.cn)
5、useCallback和useMemo的区别和使用场景
共同点: 都用于缓存数据,优化性能;两者接收的参数都是一样的,第一个参数表示一个回调函数,第二个表示依赖的数据。
区别:useCallback缓存函数,useMemo缓存函数计算return的值。
使用场景:由于useCallback中缓存的函数在任意一个state发生变化时,都会重新触发组件的更新,所以单用useCallback时反而增加了性能的损耗。为了避免这样的状况,useCallback和useMemo一起使用,可以减少不必要的渲染。
6、hoc是什么?优缺点是什么?他和hooks有什么区别
hoc(higher order components)是高阶组件,是通过接收一个组件作为参数,返回一个增强的组件的方法。
主要优点在于通过传递props去影响内层组件的状态,不直接改变内层组件的状态,降低了耦合度。
但缺点十分明显:
- 组件多层嵌套,增加维护成本;
- props值来源不清晰,且重复命名的值会被覆盖;
- refs属性不能传递。
7、讲讲diff算法
Diff算法实现了虚拟dom的最小量更新。
首先,渲染真实dom是十分耗费性能的,虚拟dom通过将真实的dom结构转化为js数据结构,在操作结束后再一次性进行渲染,达到节省性能的目的。
在这个基础上,只找到并修改新旧dom中变化的部分,这就是diff算法。
(1)首先会比较一下新旧节点是否是同一个节点(通过设定的选择器和key值进行比较),如果不是同一个节点,直接暴力删除旧节点,添加新的节点。
(2)如果是同一个节点,则要进一步比较:
- 如果这两个节点完全相同,则不做处理;
- 新节点内容如果为文本,直接替换
- 如果新的节点包含子节点,则要判断旧节点有没有子节点,如果有重复上述步骤比较,如果没有就直接清空旧节点,把新节点替换上去。
总结
其实面试题光看看总是不够的,只有重新将其梳理一遍才能从一知半解的圈圈里跳出来,真正转化成输出的时候你会发现,你其实什么都没看进去。