高级前端面试题全集
一、JavaScript 深度问题
1. 原型与继承
题目:实现一个继承方案并解释原型链
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
// 实现继承
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
// 设置原型链
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
// 测试
const child = new Child('小明', 10);
child.sayName(); // "小明"
考察点:
- 构造函数继承 vs 原型继承
Object.create
与new
的区别- 为什么需要重置
constructor
2. 事件循环与异步
题目:分析以下代码输出顺序
console.log('1');
setTimeout(() => {
console.log('2');
Promise.resolve().then(() => console.log('3'));
}, 0);
Promise.resolve().then(() => {
console.log('4');
setTimeout(() => console.log('5'), 0);
});
console.log('6');
正确答案:1 → 6 → 4 → 2 → 3 → 5
考察点:
- 宏任务 vs 微任务
- Node.js 与浏览器事件循环差异
- Promise 的执行时机
二、React 高级特性
1. Hooks 原理
题目:实现简易版的 useState
let state = [];
let setters = [];
let stateIndex = 0;
function createSetter(index) {
return function(newState) {
state[index] = newState;
render();
};
}
function useState(initialState) {
state[stateIndex] = state[stateIndex] || initialState;
setters[stateIndex] = setters[stateIndex] || createSetter(stateIndex);
const currentState = state[stateIndex];
const currentSetter = setters[stateIndex];
stateIndex++;
return [currentState, currentSetter];
}
function render() {
stateIndex = 0; // 重置索引
ReactDOM.render(<App />, document.getElementById('root'));
}
考察点:
- Hooks 的调用顺序规则
- 闭包在 Hooks 中的应用
- 为什么不能在条件语句中使用 Hooks
2. 性能优化
题目:分析并优化以下组件
function UserList({ users }) {
const [search, setSearch] = useState('');
const filteredUsers = users.filter(user =>
user.name.includes(search)
);
return (
<div>
<input onChange={(e) => setSearch(e.target.value)} />
{filteredUsers.map(user => (
<UserItem key={user.id} user={user} />
))}
</div>
);
}
优化方案:
- 使用
useMemo
缓存计算结果 - 使用
useCallback
避免子组件不必要渲染 - 添加防抖处理输入事件
- 虚拟滚动长列表优化
三、Vue 深度原理
1. 响应式原理
题目:手写简易响应式系统
class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (activeEffect) {
this.subscribers.add(activeEffect);
}
}
notify() {
this.subscribers.forEach(effect => effect());
}
}
let activeEffect = null;
function watchEffect(effect) {
activeEffect = effect;
effect();
activeEffect = null;
}
const targetMap = new WeakMap();
function getDep(target, key) {
let depsMap = targetMap.get(target);
if (!depsMap) {
depsMap = new Map();
targetMap.set(target, depsMap);
}
let dep