一、 JavaScript 基础核心考点
夯实基础,是解决复杂问题的前提。以下梳理了最高频的“前端js常见面试题”基础篇。
1. 数据类型与类型检测
JavaScript 中有 7 种基本数据类型:Undefined, Null, Boolean, Number, String, Symbol, BigInt。对象类型是 Object。
常见陷阱:typeof null 返回 'object',这是 JS 历史遗留的 Bug。对于引用类型,推荐使用 Object.prototype.toString.call() 进行精确检测。
console.log(typeof null); // "object"
console.log(Object.prototype.toString.call([])); // "[object Array]"
2. 变量提升与作用域
JS 引擎在执行代码前会进行“编译”,这一过程会将变量声明和函数声明提升到其所在作用域的顶部。
let/const:存在“暂时性死区”(TDZ),在声明之前访问变量会报错。而 var 则不会,只会赋值为 undefined。
console.log(a); // undefined
var a = 1;
console.log(b); // ReferenceError
let b = 1;
3. 闭包(Closure)
闭包是指有权访问另一个函数作用域中变量的函数。闭包的主要作用有两个:一是读取函数内部的变量,二是让这些变量的值始终保持在内存中。
面试重点:如何防止内存泄漏?如何优化闭包性能?
function outer() {
let count = 0;
return function inner() {
count++;
return count;
};
}
二、 原型链与运行机制
原型与原型链详解
每个 JavaScript 对象都有原型。原型也是一个对象,称为原型对象。每个对象都会在其内部初始化一个属性,就是 __proto__,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去 __proto__ 里找这个属性,这个 __proto__ 又会有自己的 __proto__,于是就这样一路找下去,这就是所谓的原型链。
所有函数的原型对象都是 Object.prototype,所以默认都会继承 Object.prototype.toString。
执行上下文栈(ECS)
JavaScript 是单线程语言,代码执行时会产生执行上下文。执行上下文分为三种类型:
- 全局执行上下文:只有一个,变量定义和函数声明都存储在这里。
- 函数执行上下文:有多个,函数调用时创建,函数执行完后被销毁。
- Eval 函数执行上下文:在 eval 函数中执行的代码。
执行上下文的生命周期:创建阶段 → 代码执行阶段 → 销毁阶段。
this 指向规则
this 的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定 this 到底指向谁。实际上 this 的最终指向的是那个调用它的对象。
1. 作为对象方法调用:指向该对象。
2. 作为普通函数调用:指向全局对象(非严格模式下)或 undefined(严格模式下)。
3. 构造函数调用:指向新创建的对象。
4. apply/call/bind 调用:指向指定的对象。
5. 箭头函数:没有自己的 this,继承外层作用域的 this。
三、 异步编程与 Event Loop
异步编程是前端开发的难点,也是“前端js常见面试题”中的重灾区。理解 Event Loop 是解题的关键。
1. 同步与异步
同步任务直接在主线程上执行,形成执行栈。异步任务通过回调函数放入“任务队列”中。只有当执行栈为空时,才会读取任务队列。
2. 宏任务与微任务
异步任务分为宏任务(MacroTask)和微任务(MicroTask)。
- 宏任务:script, setTimeout, setInterval, I/O, UI rendering。
- 微任务:Promise.then, MutationObserver, process.nextTick (Node.js)。
执行顺序:同步代码 → 微任务 → 宏任务 → 微任务 ...
3. Promise 链式调用
Promise 有三种状态:Pending(进行中)、Fulfilled(已成功)、Rejected(已失败)。状态一旦改变就不会再变。通过 then 和 catch 进行链式调用,每个 then 返回一个新的 Promise。
| 特性 | 宏任务 (Macrotask) | 微任务 (Microtask) |
|---|---|---|
| 执行时机 | 每次事件循环执行一个宏任务 | 当前宏任务执行完后立即执行 |
| 包含任务 | setTimeout, setInterval, setImmediate, I/O, UI Rendering | Promise.then, MutationObserver, process.nextTick |
| 优先级 | 较低 | 较高 |
四、 现代前端框架与“前端js常见面试题”拓展
随着 Vue 和 React 的普及,框架原理也成为“前端js常见面试题”的重要组成部分。以下简述核心差异与原理。
Vue 响应式原理
Vue 2 使用 Object.defineProperty 进行劫持,存在无法检测对象属性的新增或删除、数组索引变化的问题。Vue 3 改用 Proxy,可以直接监听对象和数组的变化,性能更好,且支持 Map、Set 等数据结构。
核心流程:Observer 劫持数据 → Compiler 编译模板 → Watcher 订阅者 → Dep 依赖收集。
React 虚拟 DOM
React 通过虚拟 DOM(Virtual DOM)来减少对真实 DOM 的操作。当状态变化时,生成新的虚拟 DOM 树,通过 Diff 算法对比新旧树的差异,最小化地更新真实 DOM。
Key 的作用:在列表渲染中,Key 帮助 React 识别哪些元素发生了变化、添加或删除,从而提高 Diff 效率。建议使用唯一 ID 作为 Key。
Webpack/Vite 构建工具
Webpack 是基于 Node.js 的模块打包工具,通过 Loader 处理非 JS 文件,通过 Plugin 扩展功能。Vite 基于 ES Module,在开发环境利用浏览器原生支持 ESM 实现极速热更新,在生产环境使用 Rollup 打包。
五、 前端性能优化策略
性能优化是高级工程师面试的必考题,也是“前端js常见面试题”中体现工程化能力的关键点。
1. 加载优化
- 资源压缩:使用 Gzip 压缩 JS/CSS/HTML。
- CDN 加速:将静态资源部署到 CDN,提升下载速度。
- 懒加载:图片、组件按需加载,减少首屏体积。
- 代码分割:使用 Webpack 的 Code Splitting,将路由对应的代码单独打包。
2. 渲染优化
- 减少重排与重绘:避免频繁操作 DOM,使用
transform和opacity进行动画。 - 防抖与节流:对 scroll, resize, input 等高频事件进行处理,减少函数调用频率。
- Web Worker:将计算密集型任务放到后台线程,避免阻塞主线程。
3. 缓存策略
合理利用 HTTP 缓存(强缓存 Expires/Cache-Control 和协商缓存 Last-Modified/ETag)可以极大提升二次访问速度。Service Worker 可以实现离线缓存和应用壳模式。