web前端手撕合集

这篇文章包含了一些前端常见的手撕题,和部分我在面试过程中遇到的手撕题。非算法题。

防抖

function debounce(fn, delay, immediate = false) {
    let timer
    let flag = true

    return function () {
        if (flag && immediate) {
            fn.apply(this, arguments)
            flag = false
            return
        }
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, arguments)
        }, delay)
    }
}

节流

function throttle(fn, interval) {
    let last = 0

    return function () {
        if (Date.now() - last < interval) return
        last = Date.now()
        fn.apply(this, arguments)
    }
}

柯里化

function curry(fn, ...args1) {
    if (args1.length >= fn.length) {
        return fn(...args1)
    } else {
        return (...args2) => curry(fn, ...args1, ...args2)
    }
}

浅拷贝

function shallowCopy(obj) {
    return Array.isArray(obj) ? [...obj] : { ...obj } // or
    return Object.assign(Array.isArray(obj) ? [] : {}, obj)
}

深拷贝

function deepClone(o, wm = new WeakMap()) {
    if (wm.has(o)) return wm.get(o)

    let co = Array.isArray(o) ? [] : {}
    typeof o === 'object' && o !== null && wm.set(o, co)

    for (let k of Object.getOwnPropertySymbols(o)) {
        if (typeof o[k] === 'object' && o[k] !== null) {
            co[k] = deepClone(o[k], wm)
        } else {
            co[k] = o[k]
        }
    }
    for (let k in o) {
        if (o.hasOwnProperty(k)) {
            if (typeof o[k] === 'object' && o[k] !== null) {
                co[k] = deepClone(o[k], wm)
            } else {
                co[k] = o[k]
            }
        }
    }

    return co
}

数组最大深度

function getDepth(ele) {
    if (!Array.isArray(ele)) {
        return 0
    }
    let maxDepth = 0
    ele.forEach(v => {
        maxDepth = Math.max(maxDepth, getDepth(v))
    })
    return maxDepth + 1
}

数组flat

Array.prototype.myFlat = function (depth = 1) {
    if (depth <= 0) return [...this];
    return this.reduce((p, c) => {
        if (Array.isArray(c)) {
            p.push(...c.myFlat(depth - 1))
        } else {
            p.push(c)
        }
        return p
    }, [])
}

数组reduce

Array.prototype.myReduce = function (cb, initial) {
    let res = initial !== undefined ? initial : this[0]
    let start = initial !== undefined ? 0 : 1
    for (let i = start; i < this.length; ++i) {
        res = cb(res, this[i])
    }
    return res
}

new

function myNew(con, ...args) {
    if (!con instanceof Function) {
        throw new Error()
    }
    // let obj = {}
    // obj.__proto__ = con.prototype
    // or
    let obj = null
    obj = Object.create(con.prototype)
    let result = con.apply(obj, args)
    let flag = result && (typeof result === 'object' || typeof result === 'function')
    return flag ? result : obj
}

call & apply

Function.prototype.myCall = function (context, ...args) {
    context = context === null || context === undefined ? globalThis : Object(context)
    const fnk = Symbol()
    Object.defineProperty(context, fnk, { enumerable: false, value: this })
    const r = context[fnk](...args)
    delete context[fnk]
    return r
}

Function.prototype.myApply = function (context, args) {
    context = context === null || context === undefined ? globalThis : Object(context)
    const fnk = Symbol()
    Object.defineProperty(context, fnk, { enumerable: false, value: this })
    const r = context[fnk](...args)
    delete context[fnk]
    return r
}

bind

Function.prototype.myBind = function (context, ...args) {
    context = context === null || context === undefined ? globalThis : Object(context)
    const func = this

    return function (...subArgs) {
        const allArgs = [...args, ...subArgs]
        if (new.target) {
            return new func(...allArgs)
        } else {
            return func.apply(context, allArgs)
        }
    }
}

create

function myCreate(obj) {
    function F() { }
    F.prototype = obj
    return new F()
}

instanceof

function myInstanceof(obj, con) {
    let pro = obj?.__proto__
    while (pro) {
        if (pro === con.prototype) {
            return true
        }
        pro = pro.__proto__
    }
    return false
}

Promise.all

Promise.myAll = function (promiseArr) {
    return new Promise((resolve, reject) => {
        if (!Array.isArray(promiseArr)) {
            throw new Error('argument should be array')
        }
        let count = 0,
            promiseArrLength = promiseArr.length,
            resolved = []
        for (let i = 0; i < promiseArr.length; ++i) {
            Promise.resolve(promiseArr[i]).then((res) => {
                resolved[i] = res
                ++count
                if (count === promiseArrLength) {
                    resolve(resolved)
                }
            }, (rej) => {
                reject(rej)
            })
        }
    })
}

Promise.race

Promise.myRace = function (promiseArr) {
    return new Promise((resolve, reject) => {
        if (!Array.isArray(promiseArr)) {
            throw new Error('argument should be array');
        }
        promiseArr.forEach(promise => {
            Promise.resolve(promise).then(resolve, reject)
        })
    })
}

Promise.retry

Promise.retry = function (fn, retries) {
    return new Promise((resolve, reject) => {
        Promise.resolve(fn())
            .then(resolve)
            .catch(error => {
                if (retries > 0) {
                    console.log(`Retrying... ${retries} attempts left`);
                    Promise.retry(fn, retries - 1)
                        .then(resolve)
                        .catch(reject);
                } else {
                    reject(error);
                }
            });
    })
}

Promise.queue

Promise.queue = function (promiseArr) {
    return new Promise((resolve, reject) => {
        const resultArr = [];
        // (async () => {
        //     for (let i = 0; i < promiseArr.length; i++) {
        //         try {
        //             resultArr[i] = await promiseArr[i]()
        //         } catch (err) {
        //             reject(err)
        //             return
        //         }
        //     }
        //     resolve(resultArr)
        // })()
        // or
        function runPromise(index) {
            if (index >= promiseArr.length) {
                resolve(resultArr)
                return
            }
            promiseArr[index]().then(res => {
                resultArr[index] = res
                runPromise(index + 1)
            }, err => {
                reject(err)
                return
            })
        }
        runPromise(0)
    })
}

promisify

function promisify(func) {
    return function (...args) {
        return new Promise((resolve, reject) => {
            func(...args, (err, result) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(result);
                }
            });
        });
    };
}

Event Bus

class EventBus {
    constructor() {
        this.events = {}
    }

    on(event, callback) {
        if (this.events[event] === undefined) {
            this.events[event] = new Set()
        }
        this.events[event].add(callback)
    }

    off(event, callback) {
        if (this.events[event]) {
            this.events[event].delete(callback)
            if (!this.events[event].size) delete this.events[event]
        }
    }

    emit(event, ...args) {
        if (this.events[event]) {
            this.events[event].forEach(cb => {
                cb(...args)
            })
        }
    }

    once(event, callback) {
        const onceCallback = (...args) => {
            this.off(event, onceCallback)
            callback(...args)
        }
        this.on(event, onceCallback)
    }
}

sumOf

function sum(...args1) {
    const ret = (...args2) => sum(...args1, ...args2)
    ret.sumOf = () => args1.reduce((acc, cur) => acc + cur, 0);
    return ret
}

console.log(sum(1, 2, 3).sumOf()); // 6
console.log(sum(1, 2)(3).sumOf()); // 6
console.log(sum(1)(2)(3).sumOf()); // 6

hardMan

hardMan('潘潘')

Hi! I am 潘潘.

hardMan('潘潘').study('敲码')

Hi! I am 潘潘. I am studying 敲码.

hardMan('潘潘').rest(3).study('敲码')

Hi! I am 潘潘. 【等待三秒】 I am studying 敲码.

hardMan('潘潘').restFirst(3).study('敲码')

【等待三秒】 Hi! I am 潘潘. I am studying 敲码.

function hardMan(name) {
    this.name = name;
    this.queue = []
    this.queue.push(() => {
        return new Promise(resolve => {
            console.log(`Hi! I am ${this.name}`)
            resolve()
        })
    })
    this.rest = (sec) => {
        this.queue.push(() => new Promise(resolve => {
            setTimeout(resolve, sec * 1000)
        }))
        return this
    }
    this.restFirst = (sec) => {
        this.queue.unshift(() => new Promise(resolve => {
            setTimeout(resolve, sec * 1000)
        }))
        return this
    }
    this.study = (name) => {
        this.queue.push(() => new Promise(resolve => {
            console.log(`I am studying ${name}`)
            resolve()
        }))
        return this
    }
    this._run = () => {
        if (this.queue.length) {
            const task = this.queue.shift()
            task().then(() => {
                this._run()
            })
        }
    }
    setTimeout(this._run)
    return this
}

限制最大并发

class Schedular {
    constructor() {
        this.tasks = [];
        this.runningTasks = 0;
        this.maxRunningTasks = 2;
    }

    add(task) {
        return new Promise((resolve) => {
            this.tasks.push([task, resolve]);
            this._run();
        });
    }

    _run() {
        if (this.runningTasks >= this.maxRunningTasks || !this.tasks.length) return
        this.runningTasks++;
        const [task, resolve] = this.tasks.shift();
        task().then(() => {
            this.runningTasks--;
            resolve();
            this._run();
        })
    }
}

const timeout = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const scheduler = new Schedular();
const addTask = (time, order) => {
    scheduler.add(() => timeout(time)).then(() => console.log(order))
}

addTask(1000, 1);
addTask(1000, 2);
// 1秒后输出12
addTask(1000, 3);
addTask(1000, 4);
// 再1秒后输出34

带优先级的fetch

class MyFetch {
    constructor() {
        this.queue = []
        this.count = 0
        this.maxCount = 5
    }

    fetch(url, options = {}, priority = 0) {
        return new Promise((resolve, reject) => {
            this.queue.push([priority, url, options, resolve, reject])
            this._run()
        })
    }

    _run() {
        if (this.count >= this.maxCount || this.queue.length === 0) return
        this.count++
        this.queue.sort((a, b) => b[0] - a[0])
        const [_, url, options, resolve, reject] = this.queue.shift()
        fetch(url, options).then(resolve).catch(reject).finally(() => {
            this.count--
            this._run()
        })
    }
}

重试函数 runWithRetry

重试函数:实现一个重试函数runWithRetry(handler: Function, times: number = 1, timeout?: number),支持异步

function runWithRetry(handler, times = 1, timeout) {
    return new Promise((resolve, reject) => {
        let timer;
        let timeouted = false;
        if (timeout !== undefined) {
            timer = setTimeout(() => {
                reject();
                timeouted = true;
            }, timeout);
        }
        function retry(times) {
            if (times <= 0) {
                clearTimeout(timer);
                reject();
                return;
            }
            Promise.resolve(handler()).then(
                (res) => {
                    clearTimeout(timer);
                    resolve(res);
                },
                () => {
                    if (!timeouted) retry(times - 1);
                },
            );
        }
        retry(times);
    });
}
#前端##面经#
全部评论
nb,搬进我博客整理的面试题了
2 回复 分享
发布于 2024-11-28 16:26 江西
窝尿标点
2 回复 分享
发布于 2024-11-26 09:29 湖南
你是我的神
1 回复 分享
发布于 2024-11-19 10:08 上海
进我的收藏夹吃灰去吧
1 回复 分享
发布于 2024-11-16 00:43 山东
点赞 回复 分享
发布于 2025-12-11 15:46 江苏
收藏
点赞 回复 分享
发布于 2025-04-17 10:41 广东
插眼
点赞 回复 分享
发布于 2025-04-14 21:32 陕西
你是我见过最帅的牛客男孩
点赞 回复 分享
发布于 2025-03-04 11:47 广东
你是我见过的最帅气的牛客男孩
点赞 回复 分享
发布于 2025-02-04 19:49 安徽
阿里嘎多!
点赞 回复 分享
发布于 2024-11-16 21:46 北京
m
点赞 回复 分享
发布于 2024-11-15 23:32 湖北

相关推荐

01-24 14:28
已编辑
南京信息工程大学 Java
有一堆投了没任何回信的,就记录下至少参与笔试的公司。有些公司没法记录过程或是忘记了,技术栈是java后端,因为是苏州人大多投的苏州或附近公司。参与笔试后没后文或被拒:神州信息、中国电信、极智嘉、中通快递、中国建筑、收钱吧、CVTE、小米、同程旅行、阅文集团主动放弃后续流程:苏宁易购、上海银行、中通服、苏州银行、江苏联通有面试:中国银行苏州分行-信息科技岗9.27线下笔试主要是考公题+英语+科技岗加试内容11.4线下一面包含无领导小组讨论与结构化单面12.2发差额体检12.16offer多益网络苏州9.2笔试9.8一面1.自我介绍2.项目难点3.bitmap存储签到信息为什么不用数组?4.sorted&nbsp;set底层除了跳表还有什么?5.介绍下跳表6.那为什么用跳表不用红黑树呢?7.介绍下策略模式8.手撕代码:父子继承,多态控制9.研究方向介绍下10.介绍下快排怎么做的,是否稳定?11.介绍一下堆排序12.一般什么问题会用到归并排序?13.讲讲cas14.讲讲mysql索引的底层15.那为什么sorted&nbsp;set底层不用b+树呢?16.讲讲对mysql锁的了解17.反问其中穿插了很多项目里的问题,基本完全结合项目提问。9.22HR面1.自我介绍2.什么时候开始求职的,主要投了哪些公司,是否有offer了?3.对做游戏的倾向?4.求职主要看重哪些方面因素?5.薪资期望?6.自己期望每天工作多久,一周休息几天?(挺无语的)7.对公司的了解有多少?8.为什么当时读研,有继续深造打算吗?9.研究方向是什么?10.为什么当时网申没填微博信息,平时用什么软件比较多?11.父母工作?12.测评阶段有没有印象比较深刻的题目,聊聊13.介绍下简历上的经历10.13二面(无后续)1.自我介绍2.找工作主要看重哪些方面呢?3.对游戏行业的了解4.来做游戏服务端开发有哪些优势?5.实习期间做的最复杂的业务6.实习期间下班后干什么?7.介绍下自己的项目8.对redis的了解9.实际项目里有用到redis持久化相关内容吗?10.有自己实际部署过哨兵相关内容吗?11.对java虚拟机有了解吗?12.讲讲线程池原理以及一些设计13.对数据库有什么了解?14.索引相关15.对多版本并发控制有什么了解?16.手撕代码:父子继承,多态控制博众精工10.11一面ai面(无后续)1.自我介绍2.分享在项目中遇到的棘手问题,是如何解决的?3.追问24.举例说明为了完成任务,去学习新技术的经历5.追问46.学习或工作中有没有遇到进展不顺利或想要放弃的时候,如何解决的?7.追问68.英语听力+口语题同盾科技9.21笔试10.14一面1.自我介绍2.项目问题3.分布式数据同步、数据一致性4.项目中jdk版本用的多少?5.jdk1.8中并发包相关6.线程池使用相关7.mysql索引8.B树和B+树区别9.截至目前做的自己最满意的一件事是什么10.手撕算法:简单题,链表相关10.24二面(无后续)1.自我介绍2.项目问题3.项目中有没有涉及到多线程和分布式的内容,介绍下4.gc机制了解吗?5.内存占用比较高,怎么解决?6.研究方向博云科技10.31一面1.自我介绍2.实习中技术难点3.具体项目问题4.未来发展方向?5.什么时候能来实习6.讲讲常用算法,快排归并7.讲讲对锁的了解8.讲讲最熟的map的底层、扩容等内容9.线程池相关10.java和python的区别,java的优点11.讲讲自己的优点、缺点12.反问11.2二面(无后续)1.自我介绍2.为什么没留在实习公司转正3.对大模型智能体了解4.java面向对象六大原则5.设计模式相关6.java集合相关7.mysql索引失效情况8.慢sql问题9.mysql锁相关10.什么时候行级锁会变成表级锁11.mysql主从复制12.有了解过gid吗?13.从库怎么切换成主库14.死锁什么情况下产生15.了解过生产者消费者模式吗?16.线程池相关17.未来发展方向18.反问无锡奥特维11.10一面(无后续)1.自我介绍2.讲讲spring&nbsp;boot,mysql,redis各个技术栈作用3.项目问题4.实习过程中架构和工作流程5.实习过程中遇到最大问题6.是不是自学的java,技术路线是什么,学习中间件的理由7.有没有研究过中间件源码8.讲讲xxl-job9.sql分页10.有没有用过其他数据库11.接触过哪些非关系数据库12.讲讲redis的数据结构及使用场景13.讲讲对aop的理解,底层原理14.讲讲工厂模式和策略模式15.讲讲线程池用了哪些设计模式16.讲讲sql里事务的相关语句17.对spring的ioc怎么理解的?18.如何实现依赖注入19.有没有了解过垃圾收集器20.相关垃圾收集算法21.有没有遇到服务起不来了或者oom问题,怎么处理的?22.讲讲用到的java集合23.反问民生银行苏州分行11.13一面线上无领导小组辩论,题目是大学开放相关,正反观点辩论11.24二面线下半结构群面12.8offer中金所技术苏州10.28笔试11.6一面&nbsp;hr+技术1.自我介绍2.项目问题3.研究方向4.对MCP的理解5.平时通过哪些平台学习?6.个人优缺点7.接口抽象类如何选择?8.讲讲反射9.说说代理的实现方式10.代理在spring的经典应用11.说说aop的几个核心元素12.线程的几种实现方式13.说说线程池实现与参数14.讲讲设计模式15.说说spring的一些注解16.讲讲实现事务的方式17.分布式如何实现并发安全18.有没有项目部署经验19.linux上查看进程命令20.linux查看磁盘大小命令21.数据库分页和分组函数22.反问11.21二面线下简历面12.3三面线下无领导小组讨论群面1.7offer海舟智能12.9一面线下面,先做一张小试卷,然后技术面12.12offer南京银行苏州分行10.30笔试11.27一面(无后续)线下单面,偏向半结构
点赞 评论 收藏
分享
评论
46
230
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务