一、 基础与核心概念
-
var, let, const 的区别?
- 考察点:作用域(全局/函数 vs 块级)、变量提升(Hoisting)、暂时性死区(TDZ)、是否允许重复声明、是否允许重新赋值。
-
JavaScript 的数据类型有哪些?
- 考察点:原始类型(String, Number, Boolean, Null, Undefined, Symbol, BigInt)和引用类型(Object,包括 Array, Function, Date 等)。它们在内存中如何存储?赋值时是传值还是传引用?
-
null 和 undefined 的区别?
- 考察点:含义上的区别(有意为空 vs 未定义)、typeof 操作符的结果、作为函数参数或变量初始值的用法。
-
== 和 === 的区别?
- 考察点:类型转换(强制类型转换 Type Coercion)、比较过程。能举例说明哪些情况下 == 为 true 而 === 为 false 吗?
-
什么是作用域(Scope)?什么是作用域链?
- 考察点:全局作用域、函数作用域、块级作用域(ES6)。变量查找规则。
-
什么是变量提升(Hoisting)?函数提升呢?
- 考察点:var 和 function 声明在编译阶段的行为。let 和 const 是否有提升?(有,但存在暂时性死区)。
-
什么是闭包(Closure)?闭包的应用场景有哪些?它可能导致什么问题?
- 考察点:定义(函数及其词法环境)、原理(词法作用域、作用域链持久化)、应用(数据封装/私有变量、模块化、函数柯里化、循环中的异步问题解决)、潜在问题(内存泄漏及其避免方法)。
-
this 关键字的指向在不同场景下是如何确定的?
- 考察点:全局上下文、函数直接调用、对象方法调用、构造函数 (new)、箭头函数、call/apply/bind 显式绑定。优先级是怎样的?
-
call, apply, bind 的区别和应用场景?
- 考察点:改变 this 指向、传递参数的方式、是否立即执行。手写实现 bind 是一个常见的进阶题。
-
什么是原型(Prototype)、原型链(Prototype Chain)?proto 和 prototype 的区别?
- 考察点:JavaScript 的继承机制。prototype 是函数特有的属性,proto (或 Object.getPrototypeOf()) 是实例指向其构造函数原型的链接。instanceof 的原理。
-
如何判断一个变量的类型?(多种方法及其优缺点)
- 考察点:typeof(局限性,如 typeof null, typeof [])、instanceof(原型链判断,对原始类型无效,跨 iframe 问题)、Object.prototype.toString.call()(最可靠的方式)、Array.isArray()。
二、 ES6+ 新特性
-
箭头函数 (=>) 与普通函数有什么区别?
- 考察点:this 指向(词法 this)、没有 arguments 对象(使用剩余参数 ...rest)、不能作为构造函数(不能 new)、没有 prototype 属性。
-
解构赋值(Destructuring Assignment)的用法?
- 考察点:数组解构、对象解构、默认值、剩余元素/属性、函数参数解构。
-
展开语法(Spread Syntax, ...)和剩余参数(Rest Parameters, ...)的区别和应用?
- 考察点:展开语法用于展开可迭代对象/对象,剩余参数用于收集函数多余参数。应用场景(数组/对象复制与合并、函数参数传递/收集)。
-
ES6 模块化(import/export)与 CommonJS(require/module.exports)的区别?
- 考察点:加载时机(编译时 vs 运行时)、值的性质(引用 vs 拷贝)、this 指向、语法差异。
-
Set 和 Map 数据结构与普通对象和数组的区别?
- 考察点:Set 成员唯一性、Map 键的多样性(不限于字符串)、API 使用、遍历方式。应用场景(数组去重、存储键值对)。
-
Promise 是什么?它的三种状态?如何使用?解决了什么问题?
- 考察点:解决回调地狱、异步操作的链式调用。pending, fulfilled, rejected 状态。.then(), .catch(), .finally() 的用法。Promise.all(), Promise.race(), Promise.allSettled(), Promise.any()。
-
async/await 是什么?它与 Promise 的关系?如何进行错误处理?
- 考察点:async 函数返回 Promise,await 等待 Promise 解决。更同步化的异步代码写法。使用 try...catch 处理 await 可能的拒绝状态。
-
class 语法与传统的原型继承有什么关系和区别?
- 考察点:class 是语法糖、constructor、extends、super、静态成员 (static)、getter/setter。与构造函数和原型写法的对应关系。
三、 异步编程与事件循环
-
谈谈你对 JavaScript 事件循环(Event Loop)的理解?
- 考察点:宏任务(Macrotask, 如 setTimeout, setInterval, I/O)、微任务(Microtask, 如 Promise.then/catch/finally, MutationObserver)。调用栈(Call Stack)、任务队列(Task Queue)、执行顺序。浏览器和 Node.js 的事件循环差异。
-
setTimeout(fn, 0) 的作用是什么?它会立即执行吗?
- 考察点:将其放入宏任务队列,等待当前同步代码和所有微任务执行完毕后执行。不会立即执行。
四、 DOM 操作与浏览器
-
常见的 DOM 操作有哪些?
- 考察点:获取元素(getElementById, querySelector, querySelectorAll 等)、创建/添加/删除元素、修改元素属性/内容/样式、事件监听 (addEventListener)。
-
事件冒泡(Bubbling)和事件捕获(Capturing)是什么?事件委托(Event Delegation)呢?
- 考察点:事件传播的两个阶段。事件委托的原理(利用冒泡将事件监听器添加到父元素)、优点(减少监听器数量、动态添加的子元素也能响应)。
-
localStorage, sessionStorage, Cookie 的区别?
- 考察点:生命周期、存储大小、作用域(同源)、与服务器通信方式、API 使用。
五、 性能与实践
-
什么是防抖(Debounce)和节流(Throttle)?它们的区别和应用场景?能简单实现吗?
- 考察点:优化高频触发事件(如 resize, scroll, input)。防抖(一段时间内无触发才执行)、节流(固定时间间隔内最多执行一次)。
-
什么是深拷贝(Deep Copy)和浅拷贝(Shallow Copy)?如何实现?
- 考察点:区别在于是否递归复制引用类型。浅拷贝方法(..., Object.assign)、深拷贝方法(JSON.parse(JSON.stringify()) 的局限性、structuredClone()、递归实现、库函数 lodash.cloneDeep)。
六、 代码题与场景题
- 解释代码输出: 经常会给一些包含闭包、this 指向、变量提升、异步操作的代码片段,让你预测输出并解释原因。
- 手写实现: 可能要求手写 bind, debounce, throttle, Promise, deepClone, instanceof 等。
- 数组/对象处理: 使用原生方法(map, filter, reduce, find, sort 等)高效处理数据。
- 场景设计: 如何设计一个模块、如何处理某个具体的前端交互逻辑等。
准备建议:
- 理解原理: 不要死记硬背,重点理解每个概念背后的原理和原因。
- 动手实践: 亲手编写代码来验证和加深理解,特别是对于闭包、this、异步、原型链等难点。
- 表达清晰: 练习用简洁、准确的语言描述这些概念。
- 思考关联: 注意知识点之间的联系,比如闭包和作用域、this 和函数调用方式、Promise 和事件循环等。
- 关注 ES6+: 现代 JavaScript 开发离不开 ES6 及之后的新特性,务必熟练掌握。
- 准备项目: 能够清晰地介绍你做过的项目,以及在项目中如何应用了这些 JavaScript 知识点来解决实际问题。
祝你面试成功!