2022 前端面试纪实

174 阅读7分钟

CSS

1、css的常见单位有什么,区别是啥?

  • px 像素
  • vw 相对于视口的宽度,视口被均分为100单位的vw
  • vh 相对于视口的高度,视口被均分为100单位的vh.
  • em 相对长度单位。 相对于自身的font-size大小,如果没有设置的话,font-size是可以继承的。
  • rem 是一个相对单位(root em, 根em),只相对于html根元素的font-size大小;
  • vmax 取视口宽度或高度中最大的那一边,将最大的那一边分成100份
  • vmin 取视口宽度或高度中最小的那一边,将最小的那一边分成100份

2、CSS如何实现居中,大概有4-5种?

    <div id="father">
      <div id="son"></div>
    </div>
     /* flex 方式 */
    <style>
      #father{
        width: 100vw;
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      #son {
        width: 100px;
        height: 100px;
        background-color: aqua;
      }
    </style>
    
    /* 定位 移动 */
    <style>
      #father {
        width: 100vw;
        height: 100vh;
        position: relative;
      }
      #son {
        width: 100px;
        height: 100px;
        background-color: aquamarine;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
      }
    </style>
    
    /* margin */
    <style>
     #father {
        width: 100vw;
        height: 100vh;
        position: relative;
      }
      #son {
        width: 100px;
        height: 100px;
        background-color: aquamarine;
        position: absolute;
        left: 0;
        top: 0;
        bottom: 0;
        right: 0;
        margin:auto;
      }
    </style>
    
     /* position + margin 负边距 */
    <style>      
      #father {
        width: 100vw;
        height: 100vh;
        position: relative;
      }

      #son {
        width: 100px;
        height: 100px;
        background-color: aquamarine;
        position: absolute;
        left: 50%;
        top: 50%;
        margin-left: -50px;
        margin-top: -50px;
      }
    </style>
    
    
    

3、CSS如何实现三角形?

    <div id="tr"></div>
    
    // 普通三角形
    <style>      
      #tr {
        width: 0px;
        height: 0px;
        border: 100px solid transparent;
        border-left-color: green;
       }
    </style>
    
    //直角三角形
    <style>
      #tr {
        width: 0px;
        height: 0px;
        border-top: 100px solid black;
        border-left: 100px solid transparent;
      }
    </style>
      

4、什么是重绘 重排(回流),那些因素会引起重绘重排?

重排一定会引起重绘,重绘不一定会引起重排

  • 重排
    • 定义:渲染树中部分或全部元素的尺寸结构属性发生变化时,浏览器会重新渲染部分或全部的文档,导致周围Dom元素重新排列
    • 引发重排的因素浏览器的首次渲染,页面的窗口大小元素位置元素尺寸元素内容字体大小发生变化,激活CSS伪类,或者新增或删除可见的Dom元素,会发生重排
  • 重绘
    • 定义:页面中某些元素的样式发生变化,但不会影响其再文档流中的位置,浏览器会对元素进行重新绘制
    • 引发重绘的因素:color、background相关属性、outline相关属性、border-radiusvisibilitybox-shadow,这类样式发生变化的时候,会发生重绘。
  • 避免重绘重排
    • 操作Dom时,尽量在低层级的Dom节点进行操作
    • 不要使用table布局
    • 使用CSS表达式
    • 不要频繁操作元素的样式
    • 使用absolute或fixed,使元素脱离文档流,这样他们发生变化,就不会影响其他元素
    • 使用display:none,操作结束后,将它显示出来
    • 将Dom的多个读操作/写操作放在一起,而不是读写穿插

5、如何做页面的主题切换?

JavaScript

1、数组的方法中,那些可以做迭代?

  • map 迭代数组每一项,可以给特定条件返回重新组成的新数组
  • every 迭代数组每一项,每项都符合条件才返回true,反之返回false
  • some 迭代数组每一项,只有一项符合条件就返回true,如果全部不符合才返回false
  • filter 地带数组每一项,可以添加特定的条件过筛选,返回筛选后的新数组
  • forEach 迭代数组每一项,返回undefined

2、给定字符串,提取字符串中的数字,并组成数组?

    // 不考虑小数
    const str = 'd,2f21f-kj231a'
    str.match(/\d+/g)   //['2','21','231']
    
    // 考虑小数
    const strport = 'a.23,q21.3qw2.1a'
    strport.match(/-?([1-9]\d*(\.\d*)*|0\.[1-9]\d*)/g) // ['23', '21.3', '2.1']

3、两个数组如何取交集?

     const arr1 = [1,2,34,51,3]
     const arr2 = [3,2,1,42,54]

     const arr3 = arr2.filter(item => arr1.includes(item))
     console.log(arr3); // [3, 2, 1]

4、深拷贝和浅拷贝,手写深拷贝?

深拷贝浅拷贝主要是针对引用数据类型 的。

  • 深拷贝会将整个拷贝目标复制一份。
  • 浅拷贝只是复制拷贝目标的引用地址
    // 深拷贝的实现方式
    // 1、JSON方式
    const obj = { a: 1, b: { ba: 11, bb: 12 } };
    const arr = [1, { a: 1, b: 2 }, 3]
    const cloneDeepObj = JSON.parse(JSON.stringify(obj))
    
    // 2、lodash
    const cloneDeepObj1 = _.cloneDeep(obj)
    
    // 3、**手写递归**
    const handObj = { a: 1, b: { ba: 11, bb: 12 }, c: [1, 2, 3] };
    const cloneDeepFun = (obj) => {
      let cloneObj = Array.isArray(obj) ? [] : {};
      for (let key in obj) {
        if (obj[key] instanceof Object) {
          cloneObj[key] = cloneDeepFun(obj[key])
        } else {
          cloneObj[key] = obj[key]
        }
      }
      return cloneObj
    }
    
    // 浅拷贝的实现方式
    // 1、直接赋值
    const cloneObj = obj;
    
    // 2、展开运算符
    const cloneObj1 = {...obj}
    
    // 3、Object 方法
    const cloneObj2 = Object.assign({},obj)
    
    //4、concat
    const cloneArr = [].concat(arr)

5、谈谈原型、原型链?

原型

  • 所有的对象,都可以理解为是用 new 函数创建的,所有的函数,也是对象(函数中有属性)
  • 所有函数都有个属性:prototype,称为函数原型,默认情况下,prototype是一个Object对象prototype中有一个属性constructor,是一个对象,它指向构造函数本身。
  • 所有的对象都一个属性:__proto__,称为隐式原型
  • 默认情况下 实例对象.__proto__ = 函数.prototype
  • 使用
    • 我们可以在函数原型中加入属性/方法,以增强其对象的功能,但是会导致原型污染。

原型链

  • 当访问一个对象成员时:
    • 查找对象自身是否拥有该成员,如果有,直接使用
    • 查找该对象的隐式原型是否拥有该成员,如果有,直接使用
    • 根据原型链依次查找 Tip
  • Function的__proto__指向自身的prototype
  • Object的prototype的__proto__指向null

6、讲下事件循环?

传送门🚪

JS代码在运行时,

  • 任务被分为宏任务(MacroTask/Task)微任务(MircoTask)
  • 任务队列也被分为宏任务队列(Task Queue)微任务队列(MircoTak Queue),遵从先进先出原则 微任务:
  • Promise中的then、catch、finally
  • MutationObserver(监视 DOM 变动的API,详情参考MDN
  • Process.nextTick(Node环境,通常也被认为是微任务) 宏任务: 除去微任务的所有任务都归为宏任务
  • 网络请求
  • 定时器相关
  • script的所有代码
  • ...

React

1、React的diff算法,谈谈你的理解?

2、setState是同步还是异步的?

  • setState本身并不是异步,只是因为react的性能优化机制体现为异步。在react的生命周期函数或者作用域下为异步,在原生的环境下为同步
  • 原生的环境:在DOM上绑定原生事件,setTimeOut,setInterval

3、都用过那些React Hook?

  • useState 在函数组件中声明状态(state)

  • useEffect 在函数组件中执行副作用操作

    • 副作用 数据获取,设置订阅以及手动更改 React 组件中的 DOM
    • useEffect 可以看作是componentDidMountcomponentDidUpdate 和 componentWillUnmount 这三个函数的组合
    • 默认情况下(只有一个参数的情况下),它在第一次渲染之后每次更新之后都会执行。相当于在componentDidMountcomponentDidUpdate中执行相同的代码
       useEffect(() => {
           document.title = `You clicked ${count} times`;
         });
    
    • 第二个参数传递一个[]时,相当于componentDidMount,它将只执行一次useEffect中的副作用
    • 第二个参数传递一个有依赖项的[]时,会在依赖项变化时,去执行useEffect中的副作用。相当于下方代码
        // hook,count变化时,去重新设置title
        useEffect(() => {
           document.title = `You clicked ${count} times`;
         },[count]);
         
        //class组件的生命周期函数
       componentDidUpdate(prevProps, prevState) {
         if (prevState.count !== this.state.count) {
           document.title = `You clicked ${this.state.count} times`;
         }
       }
    
    • 如果需要清除useEffect中的副作用,需要在useEffect中返回一个清除函数,这样当组件卸载的时候或者重新渲染时,会自动执行这个清除函数
         useEffect(() => {
          const timer = setInterval(() => {
             console.log('some....');
           }, 100);
    
           //  组件卸载或者重新渲染时自动执行下方代码
           return () => {
             clearInterval(timer)
           }
         });
    
  • useRef

    • 访问DOM对象的一种方式,而且无论节点如何改变,React都会将ref对象的.current属性设置为响应的DOM节点
  • useContext

    • 用于实现简单的传值问题
    const testData = {
        id:1,
        name:2
    }
    //创建Context
    const TestContext = React.createContext(testData);
    //上层组件
    function App() {
      return (
        <div className="App">
          <TestContext.Provider value={testData}>
              <Sub />
          </TestContext.Provider>
        </div>
    );
    //下层组件
    const Sub = () => {
      const data = useContext(TestContext);
      return <>{data.name}</>;
    };
    
  • useReducer

    • useState的替代方案,如果默认值是对象的话,useReducer比useState更合适,使用起来比较像redux
    const initialState = {count: 0};
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return {count: state.count + 1};
        case 'decrement':
          return {count: state.count - 1};
        default:
          throw new Error();
      }
    }
    function Counter() {
      const [state, dispatch] = useReducer(reducer, initialState);
      return (
        <>
          Count: {state.count}
          <button onClick={() => dispatch({type: 'decrement'})}>-</button>
          <button onClick={() => dispatch({type: 'increment'})}>+</button>
        </>
      );
    }
    
  • useCallback

    • 用于做性能优化时使用的hook
    • 当依赖项改变的时候才去执行内部的回调函数
    const memoizedCallback = useCallback(
      () => {
        doSomething(a, b);
      },
      [a, b],
    );
    
  • useMemo

    • 用于做性能优化的hook
    • 会在渲染期间执行
    • 当依赖项改变的时候才去重新计算
     const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    

4、setState可以在没有第二个参数的useEffect中使用吗?

不可以

  • 如果setState(12)的是简单数据类型,该state的状态将永远保持为setState(12)的值
  • 如果setState({})的是引用数据类型,页面会直接崩溃

TypeScript

1、TS中type和interface的异同?

  • interface侧重于描述数据结构type侧重于描述类型
  • 都可以描述对象或者函数
  • 都可以使用extends进行组合
  • type特有联合类型
    type Res = Array | String

2、TS中什么是元组?

  • 任意类型,但是长度有限的数组
    const tuple:[string,number] = ['tuple',123]
    
    // react 中的useState的返回值就是一个元组
    const [state,setState] = useState(0)