20道JavaScript进阶相关前端面试题及答案
JavaScript 进阶相关面试题及答案
-
什么是 ES6 的 Proxy?它有哪些常用拦截方法?适用于哪些场景?
Proxy 是 ES6 新增的对象,用于创建目标对象的代理,可拦截对象的各种操作(如属性读写、删除等)。
常用拦截方法:
get
(读取属性)、set
(设置属性)、deleteProperty
(删除属性)、has
(in
操作符)、apply
(函数调用)等。适用场景:
① 数据响应式(如 Vue3 的响应式原理);
② 数据校验(限制属性类型或值范围);
③ 日志记录(监控对象操作);
④ 实现只读对象或私有属性。 -
Reflect 对象的作用是什么?它与 Proxy 有什么关联?
Reflect 是 ES6 新增的内置对象,提供了一系列操作对象的方法(如
Reflect.get
、Reflect.set
),与 Proxy 的拦截方法一一对应。作用:
① 规范化对象操作(将分散在Object
和操作符中的功能集中);
② 提供更合理的返回值(如Reflect.set
返回布尔值表示操作成功);
③ 与 Proxy 配合,在拦截方法中调用默认行为(如handler.get = (target, key) => Reflect.get(target, key)
)。关联:Proxy 的拦截方法中,通过 Reflect 可便捷地触发对象的默认操作,避免手动实现复杂逻辑。
-
什么是 Generator 函数?它的工作原理和应用场景是什么?
Generator 函数是 ES6 的异步编程解决方案,用
function*
定义,内部用yield
暂停执行,返回迭代器对象。工作原理:调用 Generator 函数后不立即执行,而是返回迭代器,通过
next()
方法恢复执行,yield
将值传出,next()
参数可传入值。应用场景:
① 异步操作同步化表达(替代回调或 Promise 链式调用);
② 生成迭代器(遍历复杂数据);
③ 控制函数执行流程(分步执行)。示例:
function\* generator() {yield 1;yield 2;return 3;}const iter = generator();console.log(iter.next()); // { value: 1, done: false }
-
Symbol 类型有什么特性?它的主要用途是什么?
Symbol 是 ES6 新增的基本数据类型,特点:
① 唯一不可变(Symbol('a') !== Symbol('a')
);
② 不可枚举(for...in
、Object.keys
无法遍历);
③ 可作为对象属性名(避免属性名冲突)。主要用途:
① 定义对象的私有属性(无法被常规方法访问);
② 定义常量(确保唯一);
③ 扩展内置对象方法(如Symbol.iterator
定义迭代器);
④ 作为switch
语句的 case 值。 -
什么是 WeakMap 和 WeakSet?它们与 Map、Set 有什么区别?
-
WeakMap:键只能是对象,键与对象的引用是弱引用(不阻止垃圾回收),无法遍历(无
size
、keys
等方法)。 -
WeakSet:值只能是对象,值与对象的引用是弱引用,无法遍历,值唯一。
与 Map/Set 的区别:
① 引用强度:Weak 系列是弱引用,Map/Set 是强引用;
② 可遍历性:Weak 系列不可遍历,Map/Set 可遍历;
③ 适用场景:Weak 系列适合临时存储对象关联数据(如 DOM 元素的私有数据),避免内存泄漏。
- ES6 的模块化机制中,
export
和import
有哪些用法?
-
export
用于导出模块内容: -
① 命名导出(
export const a = 1;
或export { a, b };
); -
② 默认导出(
export default function() {}
,一个模块只能有一个默认导出)。 -
import
用于导入模块内容: -
① 导入命名导出(
import { a, b as c } from './m.js'
); -
② 导入默认导出(
import fn from './m.js'
); -
③ 整体导入(
import * as mod from './m.js'
); -
④ 仅执行模块(
import './m.js'
)。注意:ES6 模块是静态的,
import
/export
必须位于顶层作用域,不能在条件语句中使用。
-
什么是函数柯里化?如何实现柯里化?它的应用场景是什么?
柯里化指将接收多个参数的函数转换为一系列接收单个参数的函数的过程(如
f(a,b,c)
→f(a)(b)(c)
)。实现示例:
function curry(fn) {return function curried(...args) {if (args.length >= fn.length) {return fn.apply(this, args);}return (...nextArgs) => curried.apply(this, \[...args, ...nextArgs]);};}// 使用:const add = curry((a, b, c) => a + b + c); add(1)(2)(3) → 6
应用场景:
① 参数复用(固定部分参数);
② 延迟执行(分步传递参数);
③ 函数组合(构建复杂函数)。
-
什么是高阶函数?请举例说明其应用。
高阶函数指接收函数作为参数或返回函数的函数。
常见例子:
①Array.prototype.map
(接收回调函数);
②setTimeout
(接收回调函数);
③ 防抖节流函数(返回新函数);
④ 高阶组件(React 中接收组件返回新组件)。应用价值:
① 抽象通用逻辑(如map
抽象遍历逻辑);
② 增强函数功能(如防抖函数增强原函数);
③ 实现函数式编程范式(如compose
函数组合)。 -
JavaScript 的错误处理机制是什么?
try/catch/finally
和throw
的作用是什么?JavaScript 通过
try/catch/finally
捕获和处理错误,throw
主动抛出错误。
try {if (!num) throw new Error("数字不存在");console.log(num);} catch (e) {console.error(e.message);} finally {console.log("执行结束");}
-
try
:包裹可能出错的代码块。 -
catch
:当try
中发生错误时,执行此块(接收错误对象)。 -
finally
:无论是否出错,都会执行(常用于清理资源,如关闭文件)。 -
throw
:手动抛出错误(可是任意类型,通常是Error
对象)。示例:
- 什么是迭代器(Iterator)和可迭代对象(Iterable)?如何自定义迭代器?
const obj = {data: \[1, 2, 3],\[Symbol.iterator]\() {let index = 0;return {next: () => {if (index < this.data.length) {return { value: this.data\[index++], done: false };}return { value: undefined, done: true };}};}};for (const item of obj) { console.log(item); } // 1, 2, 3
-
可迭代对象:实现
Symbol.iterator
方法的对象(如数组、字符串、Map、Set),for...of
可遍历。 -
迭代器:
Symbol.iterator
方法返回的对象,包含next()
方法,next()
返回{ value: 值, done: 是否完成 }
。自定义迭代器示例(使对象可被
for...of
遍历):
-
什么是 Promise 的链式调用?如何处理 Promise 的错误?
Promise 的
then
方法返回新的 Promise,因此可链式调用(前一个then
的返回值作为后一个then
的参数)。错误处理方式:
①then
的第二个参数(then(null, onRejected)
);
②catch
方法(更推荐,可捕获链式中所有错误);
③finally
前的错误会被后续catch
捕获。示例:
fetchData().then(data => process(data)).then(result => show(result)).catch(error => handleError(error)) // 捕获所有环节的错误.finally(() => cleanup());
Object.assign
和扩展运算符(...
)的区别是什么?它们在拷贝对象时有什么局限?
-
共同点:均用于浅拷贝对象(仅复制表层属性)。
-
区别:
①Object.assign
是函数,可接收多个源对象(Object.assign(target, s1, s2)
);
② 扩展运算符是语法糖,更简洁(const newObj = { ...obj1, ...obj2 }
)。局限:
① 无法深拷贝(引用类型属性仅复制地址);
② 无法拷贝继承的属性和不可枚举属性;
③ 对于Symbol
作为键的属性,两者均可拷贝。
-
什么是 BigInt?它解决了什么问题?如何使用 BigInt?
BigInt 是 ES11 新增的基本数据类型,用于表示大于
2^53 - 1
的整数(JavaScript 中 Number 的最大安全整数)。解决的问题:Number 类型无法精确表示大整数(如
9007199254740993 === 9007199254740992
返回true
),BigInt 可精确表示任意大整数。使用方式:
① 在整数后加n
(如123n
);
② 用BigInt()
函数转换(如BigInt("123")
)。注意:BigInt 不能与 Number 直接运算(需转换类型),支持
+
、-
、*
、/
(整数除法)等运算符。 -
什么是 JavaScript 的内存泄漏?常见的内存泄漏场景有哪些?
内存泄漏指不再使用的内存未被释放,导致内存占用持续增加的现象。
常见场景:
① 意外的全局变量(如未声明的变量,挂载在window
上);
② 定时器未清除(setInterval
引用的 DOM 已删除但定时器仍运行);
③ 事件监听器未移除(如 DOM 元素已删除但事件仍绑定);
④ 闭包引用(长期持有不需要的变量);
⑤ 未清理的 DOM 引用(如缓存的 DOM 元素已被移除)。 -
什么是 IIFE(立即执行函数表达式)?它的作用是什么?
IIFE(Immediately Invoked Function Expression)指定义后立即执行的函数表达式。
语法:
(function() { ... })()
或(function() { ... }())
。作用:
① 创建独立作用域(避免变量污染全局);
② 封装私有变量和方法(仅通过暴露的接口访问);
③ 早期模块化的实现方式(如 jQuery 的封装)。示例:
(function() {const msg = "hello";window.logMsg = () => console.log(msg);})();logMsg(); // "hello"(外部可访问,msg不可访问)
-
什么是尾调用优化?它有什么作用?JavaScript 中如何实现尾调用优化?
尾调用指函数的最后一步是调用另一个函数(如
function f(x) { return g(x); }
)。尾调用优化:引擎在尾调用时不创建新的调用栈帧,而是复用当前栈帧,避免栈溢出(尤其递归场景)。
作用:优化递归函数的性能,防止深层递归导致的
Maximum call stack size exceeded
错误。实现条件:① 函数内部最后一步是调用函数;② 不访问当前栈帧的变量(纯函数);③ ES6 严格模式下才可能被优化(多数浏览器尚未完全支持)。
-
什么是 TypeScript?它相比 JavaScript 有哪些优势?
TypeScript 是 JavaScript 的超集,添加了静态类型系统,最终编译为 JavaScript。
优势:
① 静态类型检查(编译时发现错误,减少运行时 bug);
② 增强代码可读性(类型定义即文档);
③ 更好的 IDE 支持(自动补全、重构);
④ 支持 ES6 + 特性并向下兼容;
⑤ 适合大型项目和团队协作(规范代码,减少沟通成本)。 -
JavaScript 中的设计模式有哪些?请举例说明单例模式和观察者模式。
常见设计模式:单例模式、观察者模式、工厂模式、装饰器模式、代理模式等。
-
单例模式:确保一个类只有一个实例,并提供全局访问点(如弹窗组件、全局状态管理)。
示例:
class Singleton {constructor() {if (Singleton.instance) return Singleton.instance;Singleton.instance = this;}}const a = new Singleton();const b = new Singleton();console.log(a === b); // true
-
观察者模式:定义对象间的一对多依赖,当一个对象状态改变时,所有依赖者收到通知(如事件总线、Vue 的响应式)。
示例:
class Observer {constructor(update) { this.update = update; }}class Subject {constructor() { this.observers = \[]; }add(observer) { this.observers.push(observer); }notify(data) { this.observers.forEach(o => o.update(data)); }}
-
什么是 Web Assembly?它与 JavaScript 相比有什么优势?
Web Assembly(Wasm)是一种低级二进制指令格式,可在浏览器中高效运行,设计用于与 JavaScript 配合。
优势:
① 性能接近原生代码(执行速度比 JavaScript 快,尤其计算密集型任务);
② 支持 C/C++、Rust 等语言编译为 Wasm,扩展 Web 能力;
③ 内存安全(沙箱环境运行)。应用场景:游戏引擎、视频编辑、科学计算等高性能需求场景,与 JavaScript 协同工作(JS 调用 Wasm,Wasm 调用 JS)。
-
JavaScript 的未来发展趋势有哪些?你了解哪些 ES 的新特性?
发展趋势:
① 性能持续优化(如 JIT 编译增强);
② 类型系统增强(TypeScript 普及);
③ 更好的异步编程支持;
④ WebAssembly 深度融合;
⑤ 跨平台能力扩展(如 Node.js、桌面 / 移动端框架)。近年 ES 新特性(ES2020+):
①??
空值合并运算符(a ?? b
,仅a
为null/undefined
时取b
);
② 可选链?.
(obj?.a?.b
,避免Cannot read property
错误);
③Promise.allSettled
(等待所有 Promise 完成,无论成功失败);
④ 动态导入import()
(返回 Promise,支持条件导入);
⑤ 顶层await
(模块中直接使用await
)。