JavaScript 面试常见八股文 200 题速记版

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 不会
  • 体积有限,而且每次请求都可能带上。

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
  • 高频场景:防抖节流、深拷贝、并发请求、跨域、存储