1. 项目概述
作为一名经历过上百场技术面试的前端工程师,我深知JavaScript基础在面试中的重要性。最近整理了一份"前端面试高频考点清单",发现90%的面试都会围绕12个JS核心知识点展开。这些知识点看似基础,但能真正透彻理解的开发者不足30%。
这12个核心点涵盖了从内存管理到异步编程的关键领域,掌握它们不仅能轻松应对面试,更能显著提升日常开发能力。本文将用实战案例拆解每个知识点,分享我在大厂面试中总结的考察重点和应答技巧。
2. 核心知识点解析
2.1 作用域与闭包
作用域链决定了变量的可访问性。在Chrome调试器中执行以下代码时:
function outer() { const x = 10; return function inner() { console.log(x); }; } const closureFn = outer(); closureFn(); // 输出?闭包会保持对外部变量的引用,即使外部函数已执行完毕。常见面试陷阱是循环中的闭包问题:
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); } // 输出3次3,而非预期的0,1,2解决技巧:使用let声明或立即执行函数创建新作用域
2.2 this指向与绑定规则
this的绑定优先级:new > 显式绑定(call/apply/bind) > 隐式绑定(obj.method()) > 默认绑定(非严格模式window)
const obj = { value: 1, getValue: function() { return this.value; } }; const unboundGet = obj.getValue; console.log(unboundGet()); // undefined console.log(obj.getValue()); // 1箭头函数的this在定义时确定,无法通过call改变。React类组件中常因此出现this丢失问题。
2.3 原型与继承
每个函数都有prototype属性,实例通过__proto__访问原型。实现继承的几种方式:
// 组合继承 function Parent(name) { this.name = name; } Parent.prototype.say = function() {}; function Child() { Parent.call(this); } Child.prototype = Object.create(Parent.prototype);ES6的class本质仍是原型语法糖。面试常问instanceof原理:
function myInstanceof(left, right) { let proto = left.__proto__; while (proto) { if (proto === right.prototype) return true; proto = proto.__proto__; } return false; }2.4 事件循环机制
JS是单线程语言,通过事件循环实现异步。宏任务(macrotask)包括:
- script整体代码
- setTimeout/setInterval
- I/O操作
- UI渲染
微任务(microtask)包括:
- Promise.then
- MutationObserver
- process.nextTick(Node)
执行顺序示例:
console.log('script start'); setTimeout(() => console.log('timeout'), 0); Promise.resolve() .then(() => console.log('promise1')) .then(() => console.log('promise2')); console.log('script end'); // 输出顺序:script start -> script end -> promise1 -> promise2 -> timeout2.5 Promise实现原理
手写Promise核心逻辑:
class MyPromise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.onFulfilledCallbacks = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn()); } }; executor(resolve); } then(onFulfilled) { return new MyPromise((resolve) => { if (this.state === 'fulfilled') { resolve(onFulfilled(this.value)); } else { this.onFulfilledCallbacks.push(() => { resolve(onFulfilled(this.value)); }); } }); } }2.6 类型转换与比较
==会进行隐式类型转换,===严格相等。转换规则优先级:
- 对象转原始值:valueOf() > toString()
- 字符串转数字
- 布尔转数字
[] == ![] // true // 解析:![] => false => 0 // [] => '' => 02.7 模块化发展历程
从IIFE到ES Modules的演进:
// IIFE (function(window) { window.module = {}; })(window); // CommonJS const fs = require('fs'); // AMD define(['dep'], function(dep) {}); // ES Module import React from 'react';2.8 函数式编程要点
高阶函数与纯函数示例:
// 柯里化 const curry = (fn) => { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } else { return (...args2) => curried.apply(this, args.concat(args2)); } }; }; const sum = (a, b, c) => a + b + c; const curriedSum = curry(sum); console.log(curriedSum(1)(2)(3)); // 62.9 内存管理与GC
V8的垃圾回收机制:
- 新生代:Scavenge算法
- 老生代:标记清除+标记整理
- 内存泄漏常见场景:
- 未清除的定时器
- 闭包引用
- DOM引用未释放
// 内存泄漏示例 let elements = []; function leak() { elements.push(new Array(1000000).join('*')); }2.10 ES6+核心特性
重点新特性实战:
// 解构赋值 const { name, ...rest } = { name: 'Jack', age: 20 }; // 可选链 const street = user?.address?.street; // 空值合并 const value = input ?? 'default'; // 动态导入 const module = await import('./module.js');2.11 设计模式应用
前端常用设计模式实现:
// 观察者模式 class EventEmitter { constructor() { this.events = {}; } on(type, listener) { this.events[type] = this.events[type] || []; this.events[type].push(listener); } emit(type, ...args) { (this.events[type] || []).forEach(listener => listener(...args)); } } // 发布订阅 const pubsub = new EventEmitter(); pubsub.on('event', data => console.log(data)); pubsub.emit('event', { message: 'hello' });2.12 性能优化策略
关键优化手段:
- 防抖与节流
function debounce(fn, delay) { let timer; return function() { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, arguments), delay); }; }- 虚拟列表实现
- Web Worker计算密集型任务
- 合理使用requestAnimationFrame
3. 面试应答技巧
3.1 问题拆解方法论
遇到复杂问题时采用STAR法则:
- Situation:问题背景
- Task:需要完成的任务
- Action:采取的行动
- Result:最终结果
3.2 白板编程要点
- 先明确输入输出
- 写出测试用例
- 分步骤实现
- 考虑边界条件
// 实现深拷贝 function deepClone(obj, map = new WeakMap()) { if (obj === null || typeof obj !== 'object') return obj; if (map.has(obj)) return map.get(obj); const 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; }3.3 行为问题应答策略
回答"项目难点"时:
- 具体技术挑战
- 解决方案对比
- 最终实现效果
- 个人成长收获
4. 实战演练题库
4.1 高频手写题
- 实现Promise.all
Promise.myAll = function(promises) { return new Promise((resolve, reject) => { let count = 0; const result = []; promises.forEach((p, i) => { Promise.resolve(p) .then(res => { result[i] = res; if (++count === promises.length) resolve(result); }) .catch(reject); }); }); };- 函数柯里化
- 数组扁平化
- 发布订阅模式
4.2 原理类问题
- V8执行JS代码的流程
- 浏览器渲染原理
- HTTPS握手过程
- Webpack打包机制
4.3 场景设计题
- 实现无限滚动列表
- 前端监控系统设计
- 组件库按需加载方案
- 微前端架构实现
5. 持续学习建议
建立个人知识体系的方法:
- 定期整理脑图
- 参与开源项目
- 技术博客输出
- 模拟面试训练
推荐学习路径:
- 基础:《JavaScript高级程序设计》
- 进阶:《你不知道的JavaScript》
- 算法:《剑指Offer》
- 工程化:《Webpack实战》