前端面试中常会遇到的手写题主要考察应聘者对前端基础知识的掌握程度以及编程能力。以下是一些经典的前端手写题及其解答思路:
-
手写深拷贝(Deep Clone)
深拷贝是指复制一个对象及其所有子对象,使得新的对象和原对象完全独立。
function deepClone(obj, cache = new WeakMap()) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (cache.get(obj)) {
return cache.get(obj); // 防止循环引用
}
let cloneObj = Array.isArray(obj) ? [] : {};
cache.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], cache);
}
}
return cloneObj;
}
-
手写防抖(Debounce)函数
防抖函数用于限制某个函数的执行频率,确保函数在指定的时间间隔内只执行一次。
function debounce(fn, delay) {
let timer;
return function(...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
-
手写节流(Throttle)函数
节流函数用于限制函数的执行频率,确保函数以一定的时间间隔执行。
function throttle(fn, delay) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last > delay) {
last = now;
fn.apply(this, args);
}
};
}
-
手写 Object.create 方法
Object.create 方法用于创建一个新对象,使用现有的对象来提供新创建的对象的 __proto__。
function create(obj) {
function F() {}
F.prototype = obj;
return new F();
}
-
手写 new 运算符
new
运算符用于创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
function myNew(fn, ...args) {
if (typeof fn !== 'function') {
throw new Error('type error');
}
const obj = Object.create(fn.prototype);
const result = fn.apply(obj, args);
return result instanceof Object ? result : obj;
}
-
手写排序算法(如快速排序、冒泡排序等)
这里以冒泡排序为例
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len - 1; i++) {
for (let j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// 相邻元素两两对比
let temp = arr[j + 1]; // 元素交换
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
-
数组去重
实现一个数组去重的函数,可以使用 Set 数据结构或遍历比较。
function uniqueArray(arr) {
return [...new Set(arr)];
}
// 或者使用遍历比较的方式
function uniqueArrayByTraversal(arr) {
const uniqueSet = new Set();
const uniqueArr = [];
for (let item of arr) {
if (!uniqueSet.has(item)) {
uniqueSet.add(item);
uniqueArr.push(item);
}
}
return uniqueArr;
}
-
手写 Array.prototype.push 方法
push 方法向数组的末尾添加一个或多个元素,并返回新的长度。
Array.prototype.myPush = function(...items) {
for (let item of items) {
this[this.length] = item;
}
return this.length;
};
-
手写 Array.prototype.filter 方法
创建一个新数组,其包含通过所提供函数实现的测试的所有元素。
Array.prototype.myFilter = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('callback must be a function');
}
const result = [];
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) {
result.push(this[i]);
}
}
return result;
};
-
手写 Array.prototype.find 方法
返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
Array.prototype.myFind = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new Error('callback must be a function');
}
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) {
return this[i];
}
}
return undefined;
};