JS 手撕题高频考点
前端面试中,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]