分享一下最近面试遇到的几道前端在线笔试题
考试时间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'));