前端基础-JS手写面试题

150 阅读2分钟

节流防抖

    //防抖
    function debounce(func, delay = 300) {
        let timer = null;
        return function (...arg) {
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(() => {
                func.applay(this, ...arg);
            }, delay)
        }
    }
    let input = document.querySelector('input');
    input.oninput = debounce(function () {
        console.log(this.value);
    }, 500);


    //节流
    function throttle(func, delay = 300) {
        let flag = true;
        return function (...arg) {
            if (flag) {
                setTimeout(() => {
                    func.apply(this, arg);
                    flag = true;
                }, delay)
            }
            flag = false;
        }
    }

    window.onscroll = throttle(function(){
        console.log(123);
    },500)

发布订阅模式

    class EventEmitter {
        constructor() {
            //用于储存事件名和对应的回调函数
            this.event = {};
        }

        //订阅事件,类似事件监听
        $on(eventName, callback) {
            this.event[eventName] = this.event[eventName] || [];
            this.event[eventName].push(callback);
        }

        //删除订阅
        $off(eventName, callback) {
            this.event[eventName] = this.event[eventName].filter((itme) => { itme !== callback });
        }

        //发布事件,触发事件
        $emit(eventName, data) {
            this.event[eventName].forEach(callback => {
                callback(data);
            });
        }
    }

    //初始化 EventEmitter
    const event = new EventEmitter();

    //订阅事件
    const func1 = data => {
        console.log('我是订阅事件1', data);
    }

    const func2 = data => {
        console.log('我是订阅事件2', data);
    }
    const func3 = data => {
        console.log('我是订阅事件3', data);
    }

    event.$on('key1', func1);
    event.$on('key1', func2);
    event.$on('key3', func3);


    //发布事件
    event.$emit('key1', '哈哈');
    event.$emit('key1', '嘻嘻');
    event.$emit('key3', '哈哈 嘻嘻');

call、apply和bind

    Function.prototype.myCall = function (context, ...args) {
        context = context || window; // context 是否有传值,没有默认在全局对象window
        let key = Symbol(); //生成唯一标识
        context[key] = this; //将当前函数添加到context中
        const result = context[key](...args);//调用事件并传入参数
        delete context[key]; //删除事件
        return result;
    }

    Function.prototype.myApply = function (context, args) {
        context = context || window; // context 是否有传值,没有默认在全局对象window
        let key = Symbol(); //生成唯一标识
        context[key] = this; //将当前函数添加到context中
        const result = context[key](...args);//调用事件并传入参数
        delete context[key]; //删除事件
        return result;
    }

    Function.prototype.myBind = function (context, ...boundArgs) {
        const orgFunc = this; //保留原始函数的引用

        return function (...newArgs) {
            const mergeArgs = [...boundArgs, ...newArgs]; //合并调用时和预先传递的参数
            orgFunc.apply(context, mergeArgs); //利用apply调用原始参数
        }
    }

Promise.all() Promise.race()

    Promise.myCall = function (prmoises) {
        return new Promise((resolve, reject) => {
            if (!Array.isArray(prmoises)) {
                reject(new TypeError('参数必须为数组形式'));
            }

            let results = []; // 保存每一个 Promise 的结果
            let count = 0; // 记录成功的 Promise 个数

            promises.forEach(promise, index => {
                //将每个元素转成 Promise 对象
                Promise.resolve(promise)
                    .then((result) => {
                        results[index] = result; // 储存当前 reuslt 结果
                        count++;

                        // 当所有 Promise 都完成时,resolve 最终结果数组
                        if (count === prmoises.length) {
                            resolve(results);
                        }
                    })
                    .catch((error) => {
                        reject(error); // 如果有一个失败,则 整体失败
                    })
            });
        })
    }

    Promise.myRace = function (promises) {
        return new Promise((resolve, reject) => {
            if (!Array.isArray(prmoises)) {
                reject(new TypeError('参数必须为数组形式'));
            }

            promises.forEach((promise) => {
                Promise.resolve(promise)
                    .then((result) => {
                        resolve(result); //有一个 Promise 完成,立即完成整个 race
                    })
                    .catch((error) => {
                        reject(error); // 有一个 Promise 失败,立即失败整个 race
                    });
            })
        })
    }