前端面试题分享(2022)

2 篇文章 0 订阅
1 篇文章 0 订阅

分享一下最近面试遇到的几道前端在线笔试题

考试时间50分钟,需完成3道题,感兴趣的小伙伴可以自己试一下,个人答案写在最后了,仅供参考,有更好的写法欢迎大家在评论区一起讨论,一起学习。

/**
 * 题目01:
 *
 * 问题:实现 compareVersion 方法,用于比较两个版本号(version1、version2)
 *      如果version1 > version2,返回1;
 *      如果version1 < version2,返回-1;
 *      其他情况,返回0。
 *      版本号规则`x.y.z`,xyz均为大于等于0的整数,至少有x位
 *
 * 目标:
 * ```js
 * compareVersion('0.1', '1.1.1'); // 返回-1
 * compareVersion('13.37', '1.2 '); // 返回1
 * compareVersion('1.1', '1.1.0'); // 返回0
 * compareVersion('1.1', '1.1.1'); // 返回-1
 * ```
 */
/**
 * 题目02:
 *
 * 问题:实现一个事件分发器类,类的实例具备emit、on、off、once功能。
 *
 * 目标:
 * ```js
 * const eventer = new Eventer();
 * const hi = (name) => console.log('hi ' + name);
 * const hello = (name) => console.log('hello ' + name);
 * eventer.on('say', hi);
 * eventer.on('say', hello);
 * eventer.off('say', hi);
 * eventer.off('say');
 * eventer.once('say', hi);
 * eventer.once('say', hello);
 * eventer.emit('say', 'bro');
 * ```
 */
/**
 * 题目03:
 *
 * 问题:使用自定义hook,实现倒计时结束时显示‘活动开始’。
 *
 * 目标:
 * ```ts
 * import { render } from 'react-dom';
 * import { useEffect, useRef, useState } from 'react';
 * function useInterval(n: number) {}
 * function Time({ n }: { n: number }) {
 *   const time = useInterval(n);
 * 	 return <div>{time === 0 ? '活动开始' : `剩余时间${time}s`}</div>
 * }
 * function App() {
 * 	 return <Time n={10} />
 * }
 * render(<App />, document.getElementById('root'));
 * ```
 */

参考答案

题目一

function compareVersion(version1, version2) {
  /** 版本号正则 */
  const versionReg = /^\d+(\.\d+){0,2}$/

  if (
    version1 === version2 ||
    !versionReg.test(version1) ||
    !versionReg.test(version2)
  )
    return 0

  try {
    /** 移除掉无效的版本号 */
    version1.endsWith('.0') &&
      (version1 = version1.substring(0, version1.length - 2))
    version2.endsWith('.0') &&
      (version2 = version2.substring(0, version2.length - 2))

    const [f1 = 0, s1 = 0, t1 = 0] = version1.split(/\./g)
    const [f2 = 0, s2 = 0, t2 = 0] = version2.split(/\./g)

    const lt = (a, b) => +a > +b
    const gt = (a, b) => +a < +b

    /** 主版本号 */
    if (lt(f1, f2)) return 1
    if (gt(f1, f2)) return -1
    /** 次版本号 */
    if (lt(s1, s2)) return 1
    if (gt(s1, s2)) return -1
    /** 修订版本号 */
    if (lt(t1, t2)) return 1
    if (gt(t1, t2)) return -1
    return 0
  } catch (e) {
    return 0
  }
}

题目二

class Eventer {
  events = []

  on(name, fn) {
    this.events.push({
      name,
      fn,
      type: 'normal',
    })
  }

  once(name, fn) {
    this.events.push({
      name,
      fn,
      type: 'once',
      isEmit: false,
    })
  }

  emit(name, ...args) {
    const events = this.events.filter(
      (item) => item.name === name && !item.isEmit
    )
    for (let i = 0; i < events.length; i++) {
      const { fn, type } = events[i]
      type === 'once' && (events[i].isEmit = true)
      fn?.(...args)
    }
  }

  off(name, fn) {
    for (let i = this.events.length - 1; i >= 0; i--) {
      const item = this.events[i]
      if (item.name === name) {
        if (!fn) {
          this.events.splice(i, 1)
          continue
        }
        if (fn === item.fn) {
          this.events.splice(i, 1)
        }
      }
    }
  }
}

题目三

import { render } from 'react-dom';
import { useEffect, useRef, useState } from 'react';

function useInterval(n: number) {
  const [time, setTime] = useState<number>(n);
  const timer = useRef<NodeJs.Timer | null>(null);

  const tick = () => {
    if (time === 0) {
      clearInterval(timer.current);
      return;
    }
    setTime(time - 1);
  }

  useEffect(() => {
    timer.current = setInterval(tick, 1000);
    return () => {
      clearInterval(timer.current);
    };
  }, [n, tick]);

  return time
}

function Time({ n }: { n: number }) {
  const time = useInterval(n);

  return <div>{time === 0 ? '活动开始' : `剩余时间${time}s`}</div>;
}

function App() {
  return <Time n={10} />;
}

render(<App />, document.getElementById('root'));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值