JavaScript 面试常见八股文 200 题速记版
一、基础类型与类型判断(1-20)
1. JS 有哪些基本类型?
- undefined
- null
- boolean
- number
- string
- symbol
- bigint
2. 引用类型有哪些?
- object
- array
- function
- date
- regexp 等本质都属于对象。
3. typeof 能判断什么?
- 基本类型大多可以判断。
- 但 null 会返回 object。
4. 为什么 typeof null 是 object?
- 这是历史遗留问题。
5. 怎么准确判断数组?
- Array.isArray()。
6. instanceof 原理是什么?
- 顺着原型链找构造函数的 prototype。
7. Object.prototype.toString 有什么用?
- 更准确判断数据类型。
8. NaN 是什么?
- 表示不是一个有效数字。
- 它和自己都不相等。
9. isNaN 和 Number.isNaN 区别?
- Number.isNaN 更严格。
10. == 和 === 区别?
- == 会隐式类型转换
- === 不会
11. null 和 undefined 区别?
- null 表示空对象
- undefined 表示未定义
12. symbol 有什么用?
- 创建唯一值,常用于避免属性名冲突。
13. bigint 有什么用?
- 表示超大整数。
14. Number 精度问题为什么会发生?
- JS 使用 IEEE 754 双精度浮点数。
15. 0.1 + 0.2 为什么不等于 0.3?
- 二进制浮点数精度误差。
16. 怎么判断一个值是不是对象?
- 一般先排除 null,再看 typeof 是否是 object/function。
17. 基本类型和引用类型区别?
- 一个按值存储
- 一个按引用地址存储
18. const 定义的对象能改吗?
- 能改对象内部属性。
- 不能改变量绑定地址。
19. wrapper object 是什么?
- 基本类型的包装对象,如 new String。
20. 为什么不推荐 new String/Boolean/Number?
- 容易产生类型判断和隐式转换问题。
二、变量、作用域与闭包(21-45)
21. var、let、const 区别?
- var 有变量提升
- let/const 有暂时性死区
- const 不可重新赋值
22. 什么是变量提升?
- 声明在编译阶段被提前处理。
23. 什么是暂时性死区?
- let/const 声明前不能访问。
24. 块级作用域是什么?
- 大括号内形成独立作用域。
25. 函数作用域是什么?
- 变量只在函数内部有效。
26. 什么是作用域链?
- 当前作用域找不到变量时向上层作用域查找。
27. 什么是闭包?
- 函数访问并记住其词法作用域中的变量。
28. 闭包的本质是什么?
- 函数 + 被保留的外部变量环境。
29. 闭包有什么用?
- 封装私有变量
- 缓存数据
- 延长变量生命周期
30. 闭包有什么缺点?
- 变量可能长期不释放,导致内存占用增加。
31. for 循环里 var 为什么会有问题?
- 共用同一个变量。
32. for 循环里 let 为什么正常?
- 每次循环都有独立块级作用域。
33. 什么是词法作用域?
- 作用域由代码书写位置决定,不由调用位置决定。
34. 函数声明和函数表达式区别?
- 函数声明会整体提升。
- 函数表达式不会完整提升。
35. IIFE 是什么?
- 立即执行函数表达式。
36. 为什么以前常用 IIFE?
- 创建独立作用域,避免变量污染。
37. this 和作用域是一回事吗?
- 不是。
- this 是调用时决定,作用域是定义时决定。
38. 闭包会内存泄漏吗?
- 不一定。
- 只有无意义长期引用才可能造成问题。
39. 什么是自由变量?
- 当前作用域没有定义,去上层作用域找的变量。
40. JS 有几种作用域?
- 全局作用域
- 函数作用域
- 块级作用域
41. eval 为什么不推荐?
- 性能差
- 不安全
- 难优化
42. with 为什么不推荐?
- 作用域不明确,影响性能和可读性。
43. const 一定不可变吗?
- 不是。
- 只是绑定不可变。
44. 什么是模块作用域?
- ES Module 文件自身形成独立作用域。
45. ES Module 为什么天然避免变量污染?
- 每个模块都是独立作用域。
三、原型与继承(46-70)
46. 什么是原型?
- 对象共享属性和方法的基础机制。
47. 什么是 prototype?
- 函数身上的原型对象属性。
48. 什么是 proto?
- 对象内部指向原型的链接。
49. prototype 和 proto 区别?
- prototype 在函数上
- proto 在对象上
50. 什么是原型链?
- 对象查找属性时沿着原型向上查找的链路。
51. Object.create 有什么用?
- 以指定对象为原型创建新对象。
52. new 的过程是什么?
- 创建对象
- 连接原型
- 绑定 this
- 执行构造函数
- 返回对象
53. instanceof 原理是什么?
- 看左边对象原型链上是否出现右边构造函数 prototype。
54. 什么是继承?
- 子对象复用父对象能力的机制。
55. JS 常见继承方式有哪些?
- 原型链继承
- 构造函数继承
- 组合继承
- 寄生组合继承
- class extends
56. 为什么原型链继承有缺点?
- 引用类型属性会被实例共享。
57. 构造函数继承优缺点?
- 能避免共享引用属性
- 但不能复用原型方法
58. 组合继承为什么常见?
- 兼顾实例属性和原型方法复用。
59. 寄生组合继承为什么更优?
- 减少一次父构造函数的多余调用。
60. class 本质上是什么?
- class 是基于原型继承的语法糖。
61. extends 做了什么?
- 建立原型链继承关系。
62. super 有什么用?
- 调父类构造函数或父类方法。
63. 静态方法怎么定义?
- 用 static。
64. 静态方法能被实例调用吗?
- 不能。
- 只能类本身调用。
65. 为什么说函数也是对象?
- 因为函数可以有属性,也能被当作对象处理。
66. Function 和 Object 谁更顶层?
- 两者关系较绕,面试主要答清原型链关系即可。
67. 所有对象都有原型吗?
- 大多数有。
- Object.create(null) 创建的对象没有原型。
68. 没有原型的对象有什么特点?
- 不能继承 Object.prototype 上的方法。
69. in 和 hasOwnProperty 区别?
- in 会查原型链
- hasOwnProperty 只看自身
70. Object.hasOwn 有什么好处?
- 更安全直接判断自身属性。
四、this、call、apply、bind(71-90)
71. this 指向由什么决定?
- 调用方式决定。
72. 默认绑定是什么?
- 普通函数直接调用时,非严格模式指向全局对象。
73. 隐式绑定是什么?
- 对象调用方法时,this 指向该对象。
74. 显式绑定是什么?
- 通过 call/apply/bind 指定 this。
75. new 绑定是什么?
- new 调用时,this 指向新创建对象。
76. 箭头函数有 this 吗?
- 没有自己的 this。
- 继承外层 this。
77. 为什么箭头函数不能当构造函数?
- 没有 prototype,也没有自己的 this。
78. call 和 apply 区别?
- 参数传递方式不同。
- call 逐个传,apply 数组传。
79. bind 和 call/apply 区别?
- bind 不立即执行,返回新函数。
80. bind 返回函数能 new 吗?
- 能。
- new 优先级高于 bind 绑定的 this。
81. 事件回调里 this 指向谁?
- 普通函数常指向触发事件的元素或调用环境。
82. 定时器里的 this 指向谁?
- 普通函数通常指向全局对象或宿主环境。
83. 严格模式下普通函数 this 是什么?
- undefined。
84. 对象方法赋值给变量再调用,this 为什么变了?
- 调用位置变了,丢失隐式绑定。
85. 手写 call 核心思路是什么?
- 把函数临时挂到对象上执行。
86. 手写 apply 核心思路是什么?
- 和 call 一样,只是参数是数组。
87. 手写 bind 核心思路是什么?
- 返回一个新函数,内部 apply 原函数并处理 new 场景。
88. 箭头函数适合做对象方法吗?
- 一般不适合依赖 this 的对象方法。
89. 为什么 Vue methods 一般不用箭头函数?
- 因为会影响 this 指向。
90. this 面试主线是什么?
- 调用位置
- 绑定规则
- 箭头函数
- call/apply/bind
五、执行上下文与事件循环(91-115)
91. 什么是执行上下文?
- 代码执行时的运行环境信息。
92. 执行上下文包括什么?
- 变量环境
- 词法环境
- this 绑定
93. 调用栈是什么?
- 函数执行的栈结构。
94. 什么是事件循环?
- JS 处理同步任务、异步任务的调度机制。
95. 宏任务有哪些?
- script
- setTimeout
- setInterval
- I/O
- UI 渲染
96. 微任务有哪些?
- Promise.then
- MutationObserver
- queueMicrotask
97. 宏任务和微任务执行顺序?
- 先同步
- 再清空微任务
- 再执行下一个宏任务
98. Promise.then 为什么比 setTimeout 先执行?
- because then 是微任务,setTimeout 是宏任务。
99. async/await 本质是什么?
- Promise 的语法糖。
100. await 后面的代码什么时候执行?
- 当前同步代码后,放入微任务队列继续执行。
101. setTimeout(0) 真的是 0ms 吗?
- 不是。
- 只是尽快进入宏任务队列。
102. requestAnimationFrame 有什么特点?
- 在浏览器下一次重绘前执行。
103. queueMicrotask 有什么用?
- 显式创建微任务。
104. 渲染发生在什么时候?
- 一般在宏任务和微任务清空后的合适时机进行。
105. 为什么长任务会卡页面?
- 因为主线程被占住,无法处理渲染和交互。
106. JS 是单线程吗?
- 主线程执行 JS 是单线程。
- 但浏览器有其他线程配合。
107. Web Worker 能做什么?
- 开子线程处理计算任务。
108. Web Worker 能操作 DOM 吗?
- 不能。
109. 什么是任务队列?
- 存放待执行异步任务回调的队列。
110. 浏览器为什么要分微任务和宏任务?
- 为了更细粒度控制异步执行优先级。
111. Promise 构造函数是同步还是异步?
- executor 同步执行。
- then 回调异步执行。
112. async 函数返回什么?
- 返回 Promise。
113. await 一定会阻塞主线程吗?
- 不会像同步阻塞那样卡死主线程。
- 它只是让后续逻辑异步继续。
114. 什么是饥饿问题?
- 微任务过多可能让宏任务和渲染迟迟得不到执行。
115. 事件循环面试高频点有哪些?
- Promise
- async/await
- setTimeout
- 微任务宏任务顺序
六、Promise 与异步(116-140)
116. Promise 是什么?
- 解决异步回调地狱的对象。
117. Promise 有几种状态?
- pending
- fulfilled
- rejected
118. Promise 状态可以反复变吗?
- 不能。
- 一旦确定就不可再变。
119. then 返回什么?
- 新 Promise。
120. catch 是什么?
- then(null, onRejected) 的语法糖。
121. finally 有什么用?
- 无论成功失败都会执行。
122. Promise.resolve 有什么用?
- 把值包装成 Promise。
123. Promise.reject 有什么用?
- 返回一个 rejected Promise。
124. Promise.all 有什么特点?
- 全成功才成功
- 一个失败就失败
125. Promise.race 有什么特点?
- 谁先有结果就返回谁。
126. Promise.allSettled 有什么特点?
- 等全部结果结束,不管成功失败。
127. Promise.any 有什么特点?
- 只要一个成功就成功。
- 全失败才失败。
128. async/await 优点是什么?
- 写法更像同步,代码更清晰。
129. async/await 缺点是什么?
- 串行 await 可能影响并发性能。
130. 怎么让多个请求并发?
- Promise.all。
131. 回调地狱是什么?
- 多层回调嵌套导致代码难维护。
132. Promise 为什么能链式调用?
- then 会返回新 Promise。
133. then 里 return 普通值会怎样?
- 会变成成功态 Promise 的值。
134. then 里抛错会怎样?
- 会走后续 rejected 流程。
135. Promise 为什么比回调好?
- 状态清晰
- 链式调用
- 错误处理集中
136. 手写 Promise 核心点有哪些?
- 状态管理
- then 链式调用
- 异步执行回调
- 错误捕获
137. Promise 和 async/await 怎么选?
- 常规流程用 async/await
- 并发组合常配 Promise API
138. await 后面可以跟普通值吗?
- 可以。
- 会自动包成 Promise.resolve。
139. Promise 可以取消吗?
- 原生不能直接取消。
- 常通过外部标记或中断机制实现。
140. 异步面试主线是什么?
- Promise
- async/await
- 事件循环
- 并发控制
七、数组、字符串与常用 API(141-160)
141. map 和 forEach 区别?
- map 返回新数组
- forEach 没有返回结果
142. filter 是什么?
- 过滤出满足条件的新数组。
143. reduce 是什么?
- 把数组累计成一个结果。
144. some 和 every 区别?
- some 一个满足就 true
- every 全满足才 true
145. find 和 filter 区别?
- find 找第一个元素
- filter 找全部匹配元素
146. includes 和 indexOf 区别?
- includes 返回布尔值
- indexOf 返回索引
147. slice 和 splice 区别?
- slice 不改原数组
- splice 会改原数组
148. concat 会改原数组吗?
- 不会。
149. sort 默认有什么坑?
- 默认按字符串排序。
150. flat 有什么用?
- 数组扁平化。
151. join 有什么用?
- 数组转字符串。
152. split 有什么用?
- 字符串转数组。
153. trim 有什么用?
- 去掉字符串首尾空格。
154. startsWith/endsWith 有什么用?
- 判断字符串开头/结尾。
155. padStart/padEnd 有什么用?
- 补齐字符串长度。
156. Set 有什么特点?
- 值唯一。
157. Map 和 Object 区别?
- Map 键类型更灵活,遍历更方便。
158. WeakMap/WeakSet 有什么特点?
- 键是弱引用,不阻止垃圾回收。
159. 去重常见方式有哪些?
- Set
- filter + indexOf
- Map
160. 数组 API 面试高频点是什么?
- map/filter/reduce
- slice/splice
- sort
- 去重扁平化
八、对象、拷贝与解构(161-175)
161. 浅拷贝和深拷贝区别?
- 浅拷贝只复制一层
- 深拷贝递归复制嵌套层
162. 常见浅拷贝方式有哪些?
- Object.assign
- 展开运算符
- slice/concat
163. 常见深拷贝方式有哪些?
- JSON
- structuredClone
- 递归 + WeakMap
164. JSON 深拷贝有什么问题?
- 丢失函数、undefined、symbol
- 不能处理循环引用
165. structuredClone 有什么优点?
- 更原生、支持更多场景。
166. Object.assign 是深拷贝吗?
- 不是,是浅拷贝。
167. 展开运算符是深拷贝吗?
- 不是,是浅拷贝。
168. 解构赋值有什么用?
- 快速提取对象或数组中的值。
169. 默认值什么时候生效?
- 只有值为 undefined 时。
170. 剩余参数和展开运算符区别?
- 一个收集参数
- 一个展开内容
171. Object.keys / values / entries 区别?
- 分别返回键、值、键值对数组。
172. for…in 和 for…of 区别?
- for…in 遍历键
- for…of 遍历可迭代值
173. 什么是可枚举属性?
- 能被某些遍历方式枚举出来的属性。
174. Object.freeze 有什么用?
- 冻结对象,不能再增删改属性。
175. Object.seal 有什么用?
- 不能增删属性,但可修改已有属性。
九、ES6+ 新特性(176-190)
176. 模板字符串有什么用?
- 更方便拼接字符串和换行。
177. 箭头函数有什么特点?
- 没有自己的 this
- 写法更简洁
178. 解构赋值有什么优点?
- 简化取值代码。
179. 默认参数有什么用?
- 函数参数可直接设置默认值。
180. rest 参数是什么?
- 收集剩余参数为数组。
181. spread 语法是什么?
- 展开数组、对象、可迭代对象。
182. class 是什么?
- 原型继承语法糖。
183. module 是什么?
- JS 模块化标准。
184. import 和 require 区别?
- import 是静态编译
- require 是运行时加载
185. export default 和 export 区别?
- 一个默认导出
- 一个具名导出
186. 可选链是什么?
- ?. 安全访问深层属性。
187. 空值合并运算符是什么?
- ?? 只在 null/undefined 时取默认值。
188. 逻辑与和空值合并区别?
- || 会把 0、’’、false 也当假值
- ?? 不会
189. 动态 import 有什么用?
- 按需加载模块。
190. 顶层 await 是什么?
- 在模块顶层直接使用 await。
十、浏览器、存储与场景题(191-200)
191. localStorage 和 sessionStorage 区别?
- 生命周期和作用域不同。
192. cookie、localStorage、sessionStorage 区别?
- cookie 会随请求发送
- storage 不会
193. 为什么 cookie 不能存太大?
- 体积有限,而且每次请求都可能带上。
194. 防抖是什么?
- 停止触发一段时间后再执行。
195. 节流是什么?
- 固定时间内只执行一次。
196. 防抖和节流场景区别?
- 搜索输入常用防抖
- 滚动监听常用节流
197. 什么是跨域?
- 协议、域名、端口任一不同就是跨域。
198. 常见跨域方案有哪些?
- CORS
- 代理
- JSONP(仅 GET)
199. 什么是同源策略?
- 浏览器对不同源资源访问的安全限制。
200. JS 面试主线是什么?
- 类型
- 作用域闭包
- 原型继承
- this
- 事件循环
- Promise
- 拷贝
- ES6+
高频补充
- 核心主线:类型 -> 作用域 -> 原型链 -> this -> 事件循环 -> Promise -> 拷贝
- 高频对比:==/===、var/let/const、call/apply/bind、map/filter/reduce、slice/splice
- 高频场景:防抖节流、深拷贝、并发请求、跨域、存储