面试必刷!最全手写JS题深度解析
2025.09.19 12:48浏览量:0简介:手写JS题是前端面试的核心环节,涵盖基础语法、函数、对象、异步等关键知识点。本文系统整理高频手写题,提供解题思路与代码实现,助力开发者高效备考。
面试中最全的手写JS题:从基础到进阶的终极指南
在前端开发面试中,手写JavaScript代码题是考察候选人核心能力的关键环节。无论是基础语法、函数实现,还是对象操作、异步处理,面试官都会通过手写题检验候选人对JS本质的理解。本文将系统梳理面试中最常见的手写JS题,涵盖从基础到进阶的完整知识体系,并提供解题思路与代码实现,帮助开发者高效备考。
一、基础语法与变量操作
1. 变量类型判断
题目:实现一个函数,判断输入值的类型(如'number'
、'string'
、'boolean'
等)。
解析:
JavaScript中,typeof
运算符可以返回基本类型,但对于null
和引用类型(如Array
、Date
)的判断不够精确。需结合Object.prototype.toString.call()
实现更全面的类型判断。
代码实现:
function getType(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}
// 测试
console.log(getType(123)); // 'number'
console.log(getType([])); // 'array'
console.log(getType(null)); // 'null'
2. 深拷贝与浅拷贝
题目:实现一个深拷贝函数,支持对象、数组、日期等复杂类型的复制。
解析:
浅拷贝仅复制第一层属性,深拷贝需递归处理所有嵌套对象。需注意特殊类型(如Date
、RegExp
)的单独处理。
代码实现:
function deepClone(value) {
if (value === null || typeof value !== 'object') return value;
if (value instanceof Date) return new Date(value);
if (value instanceof RegExp) return new RegExp(value);
const clone = Array.isArray(value) ? [] : {};
for (const key in value) {
if (value.hasOwnProperty(key)) {
clone[key] = deepClone(value[key]);
}
}
return clone;
}
// 测试
const obj = { a: 1, b: { c: 2 }, d: new Date() };
const clonedObj = deepClone(obj);
console.log(clonedObj.b.c === obj.b.c); // false
二、函数与高阶函数
1. 柯里化(Currying)
题目:实现一个柯里化函数,将多参数函数转换为单参数函数的嵌套调用。
解析:
柯里化的核心是每次接收一个参数,并返回新函数,直到所有参数收集完毕。需处理剩余参数的传递。
代码实现:
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
}
}
};
}
// 测试
const sum = (a, b, c) => a + b + c;
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
2. 防抖与节流
题目:实现防抖(debounce)和节流(throttle)函数,控制高频事件的触发频率。
解析:
- 防抖:事件触发后,等待一段时间再执行,若期间再次触发则重新计时。
- 节流:固定时间间隔内只执行一次,无论触发多少次。
代码实现:
```javascript
// 防抖
function debounce(fn, delay) {
let timer = null;
return function(…args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), 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;
}
};
}
## 三、对象与原型链
### 1. 实现`new`操作符
**题目**:模拟`new`操作符的逻辑,创建一个对象并调用构造函数。
**解析**:
`new`操作符的执行步骤:
1. 创建新对象,继承构造函数的`prototype`。
2. 调用构造函数,绑定`this`到新对象。
3. 返回新对象(若构造函数无显式返回,则返回新对象)。
**代码实现**:
```javascript
function myNew(Constructor, ...args) {
const obj = Object.create(Constructor.prototype);
const result = Constructor.apply(obj, args);
return result instanceof Object ? result : obj;
}
// 测试
function Person(name) {
this.name = name;
}
const person = myNew(Person, 'Alice');
console.log(person.name); // 'Alice'
2. 实现instanceof
题目:模拟instanceof
操作符,判断对象是否为构造函数的实例。
解析:
通过遍历对象的原型链,检查是否与构造函数的prototype
匹配。
代码实现:
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
四、异步编程与Promise
1. 实现Promise
题目:实现一个简化版的Promise,支持then
、resolve
和reject
。
解析:
Promise的核心是状态管理(pending
、fulfilled
、rejected
)和异步链式调用。
代码实现:
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = null;
this.callbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.callbacks.forEach(cb => cb.onFulfilled(value));
}
};
executor(resolve);
}
then(onFulfilled) {
return new MyPromise((resolve) => {
if (this.state === 'fulfilled') {
const result = onFulfilled(this.value);
resolve(result);
} else {
this.callbacks.push({ onFulfilled });
}
});
}
}
2. 实现Promise.all
题目:实现Promise.all
,接收一个Promise数组,返回所有Promise完成后的结果数组。
解析:
需处理成功和失败两种情况,失败时直接拒绝。
代码实现:
function myPromiseAll(promises) {
return new Promise((resolve, reject) => {
const results = [];
let completed = 0;
promises.forEach((promise, index) => {
promise.then(
(value) => {
results[index] = value;
completed++;
if (completed === promises.length) resolve(results);
},
(error) => reject(error)
);
});
});
}
五、总结与备考建议
- 分模块练习:将手写题按基础语法、函数、对象、异步等分类,逐个击破。
- 理解本质:手写题的核心是考察对JS底层机制的理解,而非死记硬背。
- 模拟面试环境:在限定时间内完成题目,培养快速解题能力。
- 代码复盘:每次练习后对比标准答案,分析差异与优化点。
通过系统练习本文整理的手写JS题,开发者可全面提升对JavaScript核心知识的掌握,在面试中脱颖而出。
发表评论
登录后可评论,请前往 登录 或 注册