前端编程题

设计一个Autocomplete组件

今天是又是一个理论题,不一样的是针对逻辑思维的拷问,设计Autocomplete组件(又叫搜索组件、自动补全组件)时,你会如何设计?需要考虑什么问题呢?

如果不知道 Autocomplete 组件是什么的,你可以观察下 Google 的搜索框,多实验几次就知道啦…

通用组件

我们设计组件的原则,首先要看的就是组件的通用性、可移植性和扩展性,组件的粒度要小,其次就是保证安全性。

功能思考

  1. 支持模糊搜索,自动补全
  2. 一键清空
  3. 支持同步,异步搜索
  4. 保存历史搜索记录

设计概要

支持 slot 扩展,

支持 input,change,blur 等事件

注意安全性,提交的时候先转义

注重性能,添加防抖节流函数

注重业务侧和用户体验是最重要的,不要为了实现而实现,在保证用户体验的前提下,多思考下对其他组件和其他协作开发者的影响。

说一下你们权限的控制,路由权限以及按钮权限

假设要设计一个全局的弹窗组件你会怎么设计?

设计一个LazyMan 类

实现交通灯的逻辑

实现一个请求池

实现 36 进制加法,不得直接使用 parselnt 转化十进制进行计算,如‘1b’+‘0a’=57

实现 sortByDept()函数,被依赖最深的元素,输出到最前

sortByDept([
    {name:'a',requires:['b','c']},
    {name:'b',requires:['c']},
    {name:'b',requires:['']},
])
// 输出:
[
  {name:'c',requires:['']},
  {name:'b',requires:['c']},
  {name:'a',requires:['b','c']},
]

Promise 题目

用 JS 实现一个 MVC

字符串的规则解析:

例子:a(b)<2>c 输出:abbc,a(b(c)<3>de)<2>f 输出 abcccdebcccdef;()代表重复内容,<>代表重复的次数

function parseString(str) {
    let result = '';
    let i = 0;
    
    while (i < str.length) {
        if (str[i] === '(') {
            // 找到对应的右括号
            let bracketCount = 1;
            let j = i + 1;
            while (bracketCount > 0) {
                if (str[j] === '(') bracketCount++;
                if (str[j] === ')') bracketCount--;
                j++;
            }
            
            // 递归解析括号内的内容
            const innerContent = parseString(str.substring(i + 1, j - 1));
            
            // 获取重复次数
            let times = 1;
            if (j < str.length && str[j] === '<') {
                let k = j + 1;
                while (str[k] !== '>') k++;
                times = parseInt(str.substring(j + 1, k));
                i = k + 1;
            } else {
                i = j;
            }
            
            // 重复内容
            result += innerContent.repeat(times);
        } else {
            result += str[i];
            i++;
        }
    }
    
    return result;
}

实现一个函数将对象结构转成在树形结构

实现一个函数将小驼峰转化成大驼峰

实现超大整数相加

function bigNumAdd (num1, num2) {
    let res = '', carry = 0
    num1 = `${num1}`.split('')
    num2 = `${num2}`.split('')
    while (num1.length || num2.length || carry) {
        carry = ~~num1.pop() + ~~num2.pop()
        res = (carry % 10) + res
        carry = carry > 9
    }
    return res
}

将如下对象输出成指定数组

var obj = {
    a: {
        b: {
            c: { f: "aa" }
        },
        d: {
            e: { g: "bb" },
            h: { i: "cc" }
        },
        j: {
            k: "dd"
        }
    }
}
//预期结果 [f,g,i,c,e,h,k,b,d,j,a]

解:用层序遍历的思想

function Format (obj) {
    if (!obj) return []
    let res = []
    let queue = [obj]
    while (queue.length) {
        let arr = []
        let length = queue.length
        for (let i = 0; i < length; i++) {
            let curr = queue.shift()
            for (let s in curr) {
                if (typeof curr === 'object') {
                    queue.push(curr[s])
                    arr.push(s)
                }
            }
        }
        res = […arr, …res]
    }
    return res
}

一个大矩形内,放3 个小矩形,如何排列

image.png

  • 有穷,有六种排列方式:横、竖、上一下二、上二下一、左一右二、 左二右一,每种都有 3* 2 种排序方式,所以共 36 种
    • 若是 n 呢? 也有穷,总数是 n! * (∑ y(1,n-1)*2
  • 简单实现,我会使用 Row,Col的方式快速实现
interface LayoutNode {
 ColProps:Col
 content:string | ReactNode
 type: 'image' | 'text' | 'table';
}[ ]