前几天线上面了网易外包,问的问题还是比较基础的,不过感觉也并不全是八股,更注重代码实现层面的考察。在此对本次面试遇到的一些问题以及解答做下记录。
异步编程输入输出题
setTimeout(() => console.log(1))
const a = new Promise((resolve,reject) => {
console.log(2)
resolve(3)
console.log(4)
})
a.then(res => console.log(res))
console.log(5)
答案: 2 4 5 3 1
箭头函数中嵌套箭头函数,内部箭头函数的this指向情况
在箭头函数中嵌套箭头函数时,内部箭头函数的this指向与外部箭头函数相同,都是继承自上下文中的this值。换句话说,内部箭头函数的this指向是在外部箭头函数定义时就已经确定的,而不是在内部箭头函数调用时确定的。如果外部箭头函数的this值是undefined或者全局对象,那么内部箭头函数的this值也会是undefined或者全局对象。
下面是一个例子,其中外部箭头函数和内部箭头函数都使用了this关键字:
const obj = {
a: 1,
foo: () => {
console.log(this); // 输出全局对象或者undefined
const bar = () => {
console.log(this); // 输出与外部箭头函数相同的全局对象或者undefined
}
bar();
}
}
obj.foo();
在该例子中,外部箭头函数foo的this指向会被绑定到全局对象或者undefined上,因此内部箭头函数bar的this指向也会是全局对象或者undefined。
实现一个Promise.allSettled
function allSettled(promises) {
return new Promise(resolve => {
const results = new Array(promises.length).fill(0);
let count = 0;
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i])
.then(value => {
results[i] = { status: 'fulfilled', value };
count++;
if (count === promises.length) {
resolve(results);
}
})
.catch(reason => {
results[i] = { status: 'rejected', reason };
count++;
if (count === promises.length) {
resolve(results);
}
});
}
});
}
if (promises.length === 0) {
resolve(results)
}
});
}
实现一个自定义hook:usePrevious
需求:存储上一次的state值,如:
const a = () => {
const [A,setA] = useState()
const prev = usePrevious(A)
return
<>
<div>{A}</div>
<div>{prev}</div>
<button onClick={() => setA(A + 1)}> + </button>
</>
}
原理:使用useRef存储上一次的值,使用useEffect监测值的变化:
import { useEffect, useRef } from 'react';
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
React父子组件如何互相调用方法
-
父组件可以将自己的方法通过
props传递给子组件,子组件可以通过调用父组件传递过来的方法来触发父组件的操作。 -
父组件可以将自己的方法通过 props 传递给子组件,子组件可以通过调用父组件传递过来的方法来触发父组件的操作
-
当子组件是函数组件时,我们无法直接通过
ref属性来获取子组件实例。而当子组件是类组件时,我们可以使用this关键字来访问子组件实例的方法和属性。 -
子组件是函数组件的情形下:可以在子组件中使用
forwardRef来创建一个 ref,然后将其传递给useImperativeHandle。在useImperativeHandle中,我们可以定义一些方法或属性,然后将其返回给父组件使用。在父组件中,我们可以通过ref属性来获取子组件实例,并调用其暴露的方法或访问其属性。
-
对状态管理工具的理解,如果不用状态管理工具有没有其他方式
-
在跨组件共享数据场景较多以及数据复杂的情况下,如果不使用状态管理会比较混乱
-
如果不使用第三方状态管理工具,可以使用
Context API。使用方法如下:-
创建
Context对象可以使用
React.createContext()方法创建一个 Context 对象,该方法返回一个包含Provider和Consumer组件的对象。Provider 组件用于提供数据,Consumer 组件用于消费数据。 -
使用
Context对象我们可以在需要使用数据的组件中,使用
Consumer组件来获取外层Context数提供的数据。Consumer组件需要传入一个函数,该函数接收Provider组件提供的数据作为参数,并返回需要渲染的内容。对于函数组件来说,还可以使用
useContext()钩子来获取Provider组件提供的数据,该钩子接收一个Context对象作为参数,并返回Provider组件提供的数据。
-
实现一个React组件:将指定文本中出现的所有关键词标红
可以将指定文本根据关键词进行分割,之后根据这个数组输出不同的内容:
import React from 'react';
function HighlightText({ text, keywords }) {
const regex = new RegExp(`(${keywords.join('|')})`, 'gi');
const parts = text.split(regex);
return (
<span>
{parts.map((part, i) => (
regex.test(part) ? <mark key={i}>{part}</mark> : part
))}
</span>
);
}
也可以用字符串转html的方式:
import { useEffect, useState } from "react"
export const HighLight = ({
keyword = '苹果',
text= '这是一个苹果'
}: any) => {
const [htmlText, setHtmlText] = useState('')
useEffect(() => {
setHtmlText(text.replaceAll(keyword,`<span style="color: red">${keyword}</span>`))
},[keyword,text])
return <div dangerouslySetInnerHTML={{
__html: htmlText
}}>
</div>
}