10个常考的前端手写题

1. 实现一个简单的 JavaScript 函数,用于判断一个对象是否为空:

判断对象是否为空的函数 这个函数通过遍历对象的所有属性来检查是否有任何实际定义的键。如果在循环中找到了一个键,则立即返回false,表示对象不为空。如果没有找到任何键,则在循环结束后返回true,表示对象为空。

function isEmptyObject(obj) {
   
    for (var key in obj) {
   
        if (obj.hasOwnProperty(key)) {
   
            return false;
        }
    }
    return true;
}

2. 手写数组去重:

数组去重 第一个实现是使用传统的方法,创建一个新的数组,并利用indexOf方法检查当前元素是否已存在于新数组中,不存在则添加进去。 第二个实现利用了ES6中的Set数据结构,它不允许重复值,所以可以直接将数组转换为Set再转回数组达到去重效果。

function unique(arr) {
   
    let res = [];
    for(let i = 0; i < arr.length; i++) {
   
        if(res.indexOf(arr[i]) === -1) {
   
            res.push(arr[i]);
        }
    }
    return res;
}
// 或者使用ES6的新特性Set
function uniqueES6(arr) {
   
    return [...new Set(arr)];
}

3. 实现bind函数:

实现bind函数 JavaScript中原生的bind函数可以创建一个新的函数,在调用时设置其this上下文并传递预设参数。这里的实现同样创建了一个新的函数,并在其内部调用了原函数,同时保证了this指向和传参的正确性。

Function.prototype.myBind = function(context, ...args) {
   
    const self = this;
    return function(...newArgs) {
   
        return self.apply(context, [...args, ...newArgs]);
    };
};

4. 实现数组的map方法:

实现map方法 Array.prototype.map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。这里我们模拟了这个行为,对原数组进行遍历,并将回调函数应用于每个元素,然后将结果推入新数组。

Array.prototype.myMap = function(callback, thisArg) {
   
    const newArray = [];
    for (let i = 0; i < this.length; i++) {
   
        newArray.push(callback.call(thisArg, this[i], i, this));
    }
    return newArray;
};

5. 实现简易版的深拷贝:

简易版深拷贝 实现了一个递归函数,用于复制给定对象的所有属性和嵌套对象。当遇到非对象或null类型的值时直接返回,否则创建一个新的对象并递归地复制原对象的所有属性。

function deepClone(obj) {
   
    if (typeof obj !== 'object' || obj === null) {
   
        return obj;
    }
    let cloneObj = Array.isArray(obj) ? [] : {
   };
    for(let key in obj) {
   
        if (obj.hasOwnProperty(key)) {
   
            cloneObj[key] = deepClone(obj[key]);
        }
    }
    return cloneObj;
}

6. 实现防抖函数(debounce):

防抖函数(debounce) 防抖函数用于限制某个函数在一定时间内只能执行一次。例如在窗口 resize 或输入框连续输入事件中,防止短时间内多次触发。这里的实现是在每次调用时清除上一次的延时任务,然后重新设置一个延时任务,只有在指定时间间隔内没有再次调用时,才会执行原函数。

function debounce(func, wait) {
   
    let timeout;
    return function(...args) {
   
        clearTimeout(timeout);
        timeout = setTimeout(() => {
   
            func.apply(this, args);
        }, wait);
    };
}

7. 实现节流函数(throttle):

节流函数(throttle) 节流函数确保在一定时间内,只允许函数执行一次。与防抖不同的是,节流保证了在持续触发的情况下,至少每隔一定时间会执行一次函数。这里的实现是在触发函数时记录上一次执行的时间,如果当前时间与上次执行时间差大于设定的时间间隔,则执行函数

function throttle(func, delay) {
   
    let prev = Date.now();
    return function(...args) {
   
        const now = Date.now();
        if (now - prev >= delay) {
   
            func.apply(this, args);
            prev = now;
        }
    };
}

8. 实现 Promise 的 then 方法:

实现Promise的then方法 Promise的then方法接受两个回调函数作为参数,分别处理成功和失败的情况。这里模拟Promise的状态机,根据Promise当前状态异步执行相应的回调函数,并处理回调返回的新Promise。

MyPromise.prototype.then = function(onFulfilled, onRejected) {
   
    let self = this;
    return new MyPromise((resolve, reject) => {
   
        if (self.status === 'fulfilled') {
   
            setTimeout(() => {
    // 异步执行
                try {
   
                    let x = onFulfilled(self.value);
                    resolvePromise(x, resolve, reject);
                } catch(e) {
   
                    reject(e);
                }
            }, 0);
        } else if (self.status === 'rejected') {
   
            setTimeout(() => {
   
                try {
   
                    let x = onRejected(self.reason);
                    resolvePromise(x, resolve, reject);
                } catch(e) {
   
                    reject(e);
                }
            }, 0);
        } else {
   
            self.onResolvedCallbacks.push(() => {
   
                setTimeout(() => {
   
                    try {
   
                        let x = onFulfilled(self.value);
                        resolvePromise(x, resolve, reject);
                    } catch(e) {
   
                        reject(e);
                    }
                }, 0);
            });
            self.onRejectedCallbacks.push(() => {
   
                setTimeout(() => {
   
                    try {
   
                        let x = onRejected(self.reason);
                        resolvePromise(x, resolve, reject);
                    } catch(e) {
   
                        reject(e);
                    }
                }, 0);
            });
        }
    });
};

function resolvePromise(value, resolve, reject) {
   
    if (value instanceof MyPromise) {
   
        value.then(resolve, reject);
    } else {
   
        resolve(value);
    }
}

9. 实现简易版 Ajax 请求:

简易版Ajax请求 实现了一个基于XMLHttpRequest的简易Ajax请求函数,返回一个Promise对象。当请求完成且状态码正常时解析响应内容并resolve,否则reject。

function ajax(url, method, data) {
   
    return new Promise((resolve, reject) => {
   
        const xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
        xhr.onreadystatechange = function() {
   
            if (xhr.readyState === 4) {
   
                if (xhr.status >= 200 && xhr.status < 300) {
   
                    resolve(JSON.parse(xhr.responseText));
                } else {
   
                    reject(xhr.statusText);
                }
            }
        };
        xhr.onerror = function() {
   
            reject(xhr.statusText);
        };
        xhr.send(JSON.stringify(data));
    });
}

10. 实现一个简易版的事件委托:

实现事件委托 事件委托是一种优化事件处理的方式,通过监听父级元素的事件,然后通过事件对象判断触发事件的具体子元素,从而减少绑定事件的数量。在这个实现中,当父元素接收到事件时,会向上遍历事件传播链,查找是否匹配特定选择器的目标元素,如果匹配就执行处理器函数。

function delegateEvent(element, selector, eventType, handler) {
   
    element.addEventListener(eventType, function(event) {
   
        let target = event.target;
        while (target && target !== this) {
   
            if (target.matches(selector)) {
   
                handler.call(target, event);
                break;
            }
            target = target.parentNode;
        }
    });
}

相关推荐

  1. 10前端

    2024-02-17 20:30:04       38 阅读
  2. 【面试150】1、88合并两有序数组

    2024-02-17 20:30:04       36 阅读
  3. 前端面试 HTTP/计算机网络面试

    2024-02-17 20:30:04       34 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-17 20:30:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-17 20:30:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-17 20:30:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-17 20:30:04       20 阅读

热门阅读

  1. 基于Python的爬取天气数据及可视化分析

    2024-02-17 20:30:04       39 阅读
  2. 手机如何改自己的ip地址

    2024-02-17 20:30:04       32 阅读
  3. Spring-面试题

    2024-02-17 20:30:04       39 阅读
  4. 并查集详解及模板

    2024-02-17 20:30:04       48 阅读
  5. 学习数据结构和算法的第8天

    2024-02-17 20:30:04       40 阅读
  6. python系统学习Day3

    2024-02-17 20:30:04       31 阅读
  7. mysql读写分离

    2024-02-17 20:30:04       32 阅读
  8. Linux命令-builtin命令(执行bash内建命令)

    2024-02-17 20:30:04       31 阅读
  9. vivado DSP Block

    2024-02-17 20:30:04       32 阅读
  10. mysql存储范式简记

    2024-02-17 20:30:04       31 阅读