前端开发中,手写题可以帮助我们巩固基础知识,提升编程能力。以下是10个常考的前端手写题及其相应的代码示例和解析。
1. 实现一个深拷贝函数
深拷贝是指创建一个新对象,该对象的属性是原对象属性值的副本。下面是一个深拷贝的简单实现。
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj; // 如果是基本类型,直接返回
}
const clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]); // 递归拷贝
}
}
return clone;
}
2. 实现一个防抖函数
防抖主要用于控制函数的触发频率,常见于输入框搜索等场景。
function debounce(func, delay) {
let timer;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
3. 实现一个节流函数
节流常用于限制高频率事件的执行,如滚动事件。
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function(...args) {
if (!lastRan) {
func.apply(this, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if (Date.now() - lastRan >= limit) {
func.apply(this, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
4. 实现一个简单的事件总线
事件总线可以帮助实现不同模块之间的解耦。
class EventBus {
constructor() {
this.events = {};
}
on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
}
emit(event, ...args) {
if (this.events[event]) {
this.events[event].forEach(listener => listener(...args));
}
}
off(event, listener) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter(l => l !== listener);
}
}
5. 实现 Promise.all
Promise.all 接受一个 promise 数组,只有当所有的 promise 都成功,才会返回成功的结果。
function promiseAll(promises) {
return new Promise((resolve, reject) => {
const result = [];
let completed = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then(value => {
result[index] = value;
completed += 1;
if (completed === promises.length) {
resolve(result);
}
})
.catch(reject);
});
});
}
6. 实现一个简单的继承
实现一个简单的原型继承。
function inheritPrototype(child, parent) {
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child;
}
7. 实现一个字符串反转函数
字符串反转是一个常见的算法问题。
function reverseString(str) {
return str.split('').reverse().join('');
}
8. 实现一个数组去重
对数组进行去重,常用方法有 ES6 Set。
function uniqueArray(arr) {
return Array.from(new Set(arr));
}
// 另一种手写去重方法
function uniqueArrayManual(arr) {
return arr.filter((item, index) => arr.indexOf(item) === index);
}
9. 实现数组扁平化
将多维数组展开成一维数组。
function flattenArray(arr) {
return arr.reduce((flat, item) =>
flat.concat(Array.isArray(item) ? flattenArray(item) : item), []);
}
10. 实现一个斐波那契数列
斐波那契数列是常见的数学题,递归或循环均可实现。
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// 使用循环
function fibonacciIterative(n) {
let a = 0, b = 1, temp;
for (let i = 2; i <= n; i++) {
temp = a + b;
a = b;
b = temp;
}
return b;
}
以上是10个常见的前端手写题以及解决方案,通过这些题目,可以提升你的编程能力和面试技巧。通过不断练习,你将能够更加自信地应对面试中的各种问题。