2025前端面试题—JavaScript篇
好的,下面是 JavaScript 部分的经典面试题 + 中文解析 + 示例代码(demo)。这部分内容偏重核心机制与实战能力,适合系统复习、面试冲刺。
🧠 JavaScript 面试题(共 30 题)+ 详细解析与 Demo
1. JavaScript 有哪些数据类型?
答:
-
基本类型(值类型):
number、string、boolean、undefined、null、symbol、bigint -
引用类型:
object(包括数组、函数、对象等)
2. typeof null 是什么?为什么?
答:
typeof null === 'object'
这是 JS 语言早期的设计缺陷,历史遗留问题。
3. 判断数组的方法有哪些?
答:
Array.isArray(arr); // ✅ 推荐
Object.prototype.toString.call(arr) === '[object Array]'
arr instanceof Array
4. == 和 === 有什么区别?
答:
-
==会进行类型转换 -
===不进行类型转换,类型和值都必须相等
0 == '0' // true
0 === '0' // false
5. 什么是闭包?有什么作用?
答:
闭包是函数和其词法作用域的组合。
作用是:保护变量不被销毁、实现私有变量、缓存变量
示例:
function outer() {
let count = 0;
return function () {
return ++count;
};
}
const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
6. 什么是作用域链?
答:
当访问变量时,JS 会从当前作用域向上查找,直到全局作用域,形成链式结构,称为作用域链。
7. 什么是原型和原型链?
答:
-
每个对象都有一个
__proto__指向其构造函数的prototype -
多个对象通过原型链连接,实现继承查找
8. 什么是 this?它是如何绑定的?
答:
this 指向取决于调用方式:
| 调用方式 | this 指向 |
|---|---|
| 普通函数调用 | 全局对象(严格模式下是 undefined) |
| 方法调用 | 谁调用指向谁 |
| 构造函数 new | 指向新创建的实例对象 |
| 箭头函数 | 没有自己的 this,继承外层 |
| call/apply/bind | 显式绑定 |
9. 如何实现函数防抖和节流?
答:
-
防抖(debounce):最后一次触发后一段时间才执行
-
节流(throttle):规定间隔时间执行一次
function debounce(fn, delay) {
let timer;
return function () {
clearTimeout(timer);
timer = setTimeout(fn, delay);
};
}
10. 什么是浅拷贝和深拷贝?
答:
-
浅拷贝:只复制一层属性,引用类型共享
-
深拷贝:递归复制所有层级
// 浅拷贝
const shallow = Object.assign({}, obj);
// 深拷贝(简单场景)
const deep = JSON.parse(JSON.stringify(obj));
11. 如何判断一个对象是空对象?
答:
Object.keys(obj).length === 0;
JSON.stringify(obj) === '{}';
12. 事件冒泡与捕获是什么?
答:
-
捕获阶段:从 document 一直向目标元素传播
-
冒泡阶段:从目标元素向上传播到 document
默认执行的是冒泡阶段,可用 addEventListener('click', fn, true) 监听捕获。
13. 什么是事件委托?
答:
通过将事件绑定在父级,利用事件冒泡,处理子元素的事件,提高性能。
document.getElementById('list').addEventListener('click', e => {
if (e.target.tagName === 'LI') {
console.log(e.target.innerText);
}
});
14. setTimeout 和 setInterval 的区别?
答:
-
setTimeout(fn, t):延迟执行一次 -
setInterval(fn, t):每隔 t 毫秒重复执行
15. Promise 是什么?有哪些状态?
答:
-
Promise 是异步编程解决方案,有三种状态:
-
pending(进行中)
-
fulfilled(已成功)
-
rejected(已失败)
-
new Promise((resolve, reject) => {
// ...
})
.then(res => {})
.catch(err => {});
16. async/await 的本质?
答:
是基于 Promise 的语法糖,使异步代码看起来像同步写法。
async function fetchData() {
const res = await fetch(url);
const data = await res.json();
}
17. var、let、const 有何区别?
| 特性 | var | let/const |
|---|---|---|
| 作用域 | 函数级 | 块级作用域 |
| 提升 | 有,初始化为 undefined |
有但不初始化,存在暂时性死区 |
| 重复声明 | 允许 | 不允许 |
| const | 不可变 | 不能重新赋值 |
18. new 操作符的原理?
答:
-
创建空对象
-
绑定
this -
执行构造函数
-
返回对象
19. 手写 call、apply、bind 简化版
Function.prototype.myCall = function (ctx, ...args) {
ctx = ctx || window;
ctx.fn = this;
const result = ctx.fn(...args);
delete ctx.fn;
return result;
};
20. 常见数组方法有哪些?
-
遍历类:
forEach、map、filter、reduce -
查找类:
find、includes、indexOf -
变异类:
push、pop、splice、sort -
不变类:
slice、concat
21. 如何实现数组去重?
[...new Set(arr)]
或使用:
arr.filter((item, index) => arr.indexOf(item) === index)
22. JS 如何判断变量是对象?
typeof obj === 'object' && obj !== null
23. JSON.stringify 中不能序列化哪些?
-
undefined -
function -
symbol
24. Symbol 有什么作用?
答:
创建独一无二的值,常用于对象属性,避免冲突。
25. 什么是内存泄漏?
答:
不再使用的对象仍被引用,无法释放内存。常见场景:全局变量、闭包、定时器未清除、DOM 引用未释放。
26. 什么是垃圾回收机制?
答:
浏览器采用标记清除算法或引用计数,自动释放不再被引用的对象。
27. 事件循环(event loop)是什么?
答:
JS 单线程通过事件循环机制处理异步任务。主线程先执行同步任务,然后处理微任务(如 Promise)、再处理宏任务(如 setTimeout)。
28. 什么是微任务和宏任务?
答:
-
微任务:
Promise.then、MutationObserver -
宏任务:
setTimeout、setInterval、requestAnimationFrame
29. 解释节流函数 throttle 的实现原理
function throttle(fn, delay) {
let last = 0;
return function () {
const now = Date.now();
if (now - last >= delay) {
fn.apply(this, arguments);
last = now;
}
};
}
30. 深拷贝如何实现?
简单版本:
JSON.parse(JSON.stringify(obj));
通用版本:
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
const copy = Array.isArray(obj) ? [] : {};
for (let key in obj) {
copy[key] = deepClone(obj[key]);
}
return copy;
}

浙公网安备 33010602011771号