前端面试中,JS 手撕题是高频考点,主要考察 编程能力、算法思维、JS 核心知识。以下是最常见的手撕题分类 + 代码示例:
目录
- 📌 1. 手写函数柯里化
- 📌 2. 手写 `debounce`(防抖)
- 📌 3. 手写 `throttle`(节流)
- 📌 4. 手写深拷贝
- 📌 5. 手写 `new` 操作符
- 📌 6. 手写 `call` / `apply` / `bind`
- 📌 7. 手写 `Promise.all`
- 📌 8. 实现 LRU 缓存
- 📌 9. 手写 `instanceof`
- 📌 10. 数组去重
📌 1. 手写函数柯里化
题目:实现一个 curry(fn)
函数
function curry(fn, ...args) {return args.length >= fn.length? fn(...args): (...nextArgs) => curry(fn, ...args, ...nextArgs);
}// 示例函数
function sum(a, b, c) {return a + b + c;
}const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
console.log(curriedSum(1, 2)(3)); // 6
📌 2. 手写 debounce
(防抖)
题目:实现 debounce(fn, delay)
function debounce(fn, delay) {let timer;return function (...args) {clearTimeout(timer);timer = setTimeout(() => fn.apply(this, args), delay);};
}// 示例:输入框搜索
const search = debounce(() => console.log("搜索 API 请求"), 500);
document.getElementById("searchInput").addEventListener("input", search);
📌 3. 手写 throttle
(节流)
题目:实现 throttle(fn, delay)
function throttle(fn, delay) {let lastTime = 0;return function (...args) {const now = Date.now();if (now - lastTime >= delay) {fn.apply(this, args);lastTime = now;}};
}// 示例:鼠标滚动触发
const handleScroll = throttle(() => console.log("滚动中..."), 1000);
window.addEventListener("scroll", handleScroll);
📌 4. 手写深拷贝
题目:实现 deepClone(obj)
function deepClone(obj, map = new WeakMap()) {if (typeof obj !== "object" || obj === null) return obj;if (map.has(obj)) return map.get(obj); // 处理循环引用let clone = Array.isArray(obj) ? [] : {};map.set(obj, clone);for (let key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key], map);}}return clone;
}// 示例
const obj = { a: 1, b: { c: 2 } };
const copy = deepClone(obj);
console.log(copy);
📌 5. 手写 new
操作符
题目:实现 myNew(fn, ...args)
function myNew(fn, ...args) {const obj = Object.create(fn.prototype); // 创建空对象并继承构造函数原型const result = fn.apply(obj, args); // 执行构造函数return result instanceof Object ? result : obj; // 处理返回值
}// 示例
function Person(name) {this.name = name;
}
const p = myNew(Person, "Alice");
console.log(p.name); // Alice
📌 6. 手写 call
/ apply
/ bind
✅ 手写 call
Function.prototype.myCall = function (context, ...args) {context = context || window;const fnKey = Symbol();context[fnKey] = this;const result = context[fnKey](...args);delete context[fnKey];return result;
};// 示例
function greet() {console.log(`Hello, ${this.name}`);
}
const obj = { name: "Alice" };
greet.myCall(obj); // Hello, Alice
✅ 手写 apply
Function.prototype.myApply = function (context, args = []) {context = context || window;const fnKey = Symbol();context[fnKey] = this;const result = context[fnKey](...args);delete context[fnKey];return result;
};
✅ 手写 bind
Function.prototype.myBind = function (context, ...args) {const self = this;return function (...innerArgs) {return self.apply(context, [...args, ...innerArgs]);};
};// 示例
const boundFn = greet.myBind(obj);
boundFn(); // Hello, Alice
📌 7. 手写 Promise.all
题目:实现 myPromiseAll(promises)
function myPromiseAll(promises) {return new Promise((resolve, reject) => {let results = [];let count = 0;if (promises.length === 0) resolve([]);promises.forEach((p, index) => {Promise.resolve(p).then(value => {results[index] = value;count++;if (count === promises.length) resolve(results);},error => reject(error));});});
}// 示例
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = new Promise(resolve => setTimeout(() => resolve(3), 1000));myPromiseAll([p1, p2, p3]).then(console.log); // [1, 2, 3]
📌 8. 实现 LRU 缓存
题目:设计一个 LRUCache
class LRUCache {constructor(capacity) {this.capacity = capacity;this.cache = new Map();}get(key) {if (!this.cache.has(key)) return -1;let value = this.cache.get(key);this.cache.delete(key);this.cache.set(key, value);return value;}put(key, value) {if (this.cache.has(key)) this.cache.delete(key);this.cache.set(key, value);if (this.cache.size > this.capacity) {this.cache.delete(this.cache.keys().next().value); // 删除最早的键}}
}// 示例
const cache = new LRUCache(2);
cache.put(1, "A");
cache.put(2, "B");
console.log(cache.get(1)); // A
cache.put(3, "C"); // 淘汰 key=2
console.log(cache.get(2)); // -1
📌 9. 手写 instanceof
题目:实现 myInstanceOf(obj, constructor)
function myInstanceOf(obj, constructor) {let proto = Object.getPrototypeOf(obj);while (proto) {if (proto === constructor.prototype) return true;proto = Object.getPrototypeOf(proto);}return false;
}// 示例
console.log(myInstanceOf([], Array)); // true
console.log(myInstanceOf({}, Array)); // false
📌 10. 数组去重
const uniqueArray = arr => [...new Set(arr)];
console.log(uniqueArray([1, 2, 2, 3])); // [1, 2, 3]