面试后的亡羊补牢
微软实习了一个半月了,参与秋招并不是觉得自己不能转正,更多的是希望能把自己带入到应届生的身份中去,掂量掂量自己几斤几两。
也是一个好机会,通过面试去查漏补缺,看看自己的提升方向,在这儿整理一下自己回答的不好或者觉得有价值的问题。
虽说是提起批,但仍然问了相当多的八股文,很多问题我在开发中并没有关注,值得考究。
React 中 key 的作用是什么?具体渲染的时候是如何提升性能的?
key 是 React 中用来对组件进行标记的唯一标识(这里的唯一是指局部唯一)。简单来说 key 帮助 React 识别哪些元素被改变了,例如添加或删除。
React 官方的例子很好地解释了 key 能提升性能的原因。
在更改列表的时候,例如我希望往列表尾部插入一个新的元素:
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
那么此时 React 自然知道只需要往后增加一个元素即可,不需要动前两个元素,这棵树实际上只多了一个 node。
但是,如果需要往列表头增加一个元素:
<ul>
<li>Duke</li>
<li>Villanova</li>
</ul>
<ul>
<li>Connecticut</li>
<li>Duke</li>
<li>Villanova</li>
</ul>
这棵树上原来两个 nodes 的位置也变了,所以 React 进行的操作不只是添加,而是变更了 1 + 2 个结点。
但是如果当使用了 key 之后,React 可以使用 key 去匹配树上的每个结点:
<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
这样子,React 就知道,只有 key = "2014"
的元素需要被更改。
useMemo 和 useCallback 分别是用来做什么的?具体怎么使用?
useMemo
接收两个参数,第一个参数是个函数,返回值是需要保存的值,第二个参数是一个数组,作为依赖项,变化的时候会执行第一个函数,产生新的值。
应用场景:
-
缓存,减少运算量。
useMemo(() => { // 大量运算 return number; }, [props.n]) // 只有 props.n 变化,才会重新计算 number
-
减少
dom
循环// 保证只有在 selectList 的变化的时候,才会重新执行这个循环 {useMemo(() => ( <div>{ selectList.map((i, v) => ( <span className={style.listSpan} key={v} > {i.patentName} </span> ))} </div> ), [selectList])}
-
减少子组件渲染
/* 只有当 props.list 列表改变的时候,子组件才渲染 */ const goodListChild = useMemo(()=> <GoodList list={ props.list } /> ,[ props.list ])
useCallback
接受的参数和 useMemo
类似,区别在于返回的是函数本身,而不是函数的运行结果。
const DemoUseCallback=({ id })=>{
const [number, setNumber] = useState(1)
/* 此时usecallback的第一参数 (sonName)=>{ console.log(sonName) }
经过处理赋值给 getInfo */
const getInfo = useCallback((sonName)=>{
console.log(sonName)
},[id])
return <div>
{/* 点击按钮触发父组件更新 ,但是子组件没有更新 */}
<button onClick={ ()=>setNumber(number+1) } >增加</button>
<DemoChildren getInfo={getInfo} />
</div>
}
类组件和函数组件有什么区别?
标准答案:函数式组件捕获了渲染所用的值。(Function components capture the rendered values.)
React 的 contributor 之一 Dan Abramov 的例子非常的清晰易懂。
假设有两个组件,一个是函数组件,一个是类组件,两个都通过 props.user
从父组件那边获取了一个值 user
,并且执行了一个异步的操作(使用 setTimeout 延迟了 3 秒输出 user
)。
对于类组件,通过 this.props.user
来获取当前的 user
信息,而函数组件通过 props.user
。
两者很大的差别就是有没有用 this
,对于使用 this
的类组件,他们拿到的永远都是实例上最新的值,因为类组件是跟实例绑定的。
所以,在延迟 3 秒的期间,如果我们改变了 user
的值,那么,类组件最后输出的就是最新的 user
值。
但是,对于函数组件而言,即时等待期间改变 user
的值,最后输出的也是原 user
的值,因为函数式组件是和一个特定的渲染绑定在了一起。
在 React 中,props 是不可变的,而 this 是可变的。
React 的新旧版生命周期
old lifecycle
new lifecycle
HTTPS 是怎么做到加密的
- 浏览器向服务器发送
client_random
和加密方法列表。 - 服务器接收到,返回
server_random
、加密方法以及公钥。 - 浏览器接收,接着生成另一个随机数
pre_random
, 并且用公钥加密,传给服务器。(敲黑板!重点操作!) - 服务器用私钥解密这个被加密后的
pre_random
。
现在浏览器和服务器有三样相同的凭证:client_random
、server_random
和pre_random
。然后两者用相同的加密方法混合这三个随机数,生成最终的密钥
。
然后浏览器和服务器尽管用一样的密钥进行通信,即使用对称加密
。
这个最终的密钥是很难被中间人拿到的,为什么呢? 因为中间人没有私钥,从而拿不到pre_random,也就无法生成最终的密钥了。
常见的 HTTP Headers
- Accept: text/html, image/png
- Authorization
- Host: shopapi.ethanloo.cn
- Connection: keep-alive
- User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.57
- Origin: https://mooc.ethanloo.cn
- Allow: GET
- Content-type: application/json; charset=utf-8