【20230525】网易外包面经

1,028 阅读4分钟

前几天线上面了网易外包,问的问题还是比较基础的,不过感觉也并不全是八股,更注重代码实现层面的考察。在此对本次面试遇到的一些问题以及解答做下记录。

异步编程输入输出题

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();

在该例子中,外部箭头函数foothis指向会被绑定到全局对象或者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 对象,该方法返回一个包含ProviderConsumer组件的对象。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>
}