第8天:前端面试经典五问

今天复习了前端面试中最高频的七道经典题,涵盖 React/Vue 的 key 原理、map(parseInt) 陷阱、防抖节流、ES6 数据结构、遍历与拷贝、继承区别等。以下是问答整理。


第1题:React / Vue 中列表 key 的作用

我的回答:

  • key 作为唯一标识,在渲染时避免不必要的重复创建与渲染。没有 key 时默认使用 index?
  • 用 index 作为 key,增删改操作会导致索引错乱,列表重新排序时每个 DOM 元素的 key 都会改变。
  • 如果两个子组件使用了相同的 key,只会渲染第一个,忽略或覆盖第二个。

补充:

  • **key 的核心作用:**帮助框架(React/Vue)识别哪些元素改变了、添加了、删除了,从而优化 DOM 更新。在 diff 算法中,key 用于判断节点是否可复用。如果没有 key,框架会采用"就地复用"策略(如 React 默认会复用相同位置的节点,可能导致状态错乱)。
  • **没有 key 时的默认行为:**React 不会自动使用 index,而是警告并采用"就地复用"。Vue 如果不用 key,会尽量复用元素,但可能导致状态问题。所以即使没有警告,也强烈建议总是提供唯一的 key。
  • **index 作 key 的问题:**当列表顺序变化(增、删、排)时,index 对应的内容可能发生变化,导致不必要的 DOM 更新或组件状态错乱(比如输入框内容错位)。只有列表是静态的、不会重新排序时才勉强可用。
  • **重复 key:**React 会在控制台警告,但实际渲染时,后出现的相同 key 的组件会被忽略或覆盖(具体取决于实现)。总之应避免重复。

第2题:['1','2','3'].map(parseInt)

我的回答:

  • 输出 1, NaN, NaN。
  • parseInt 接收两个参数:字符串和进制。map 回调传入三个参数:当前值、索引、原数组。因此 parseInt 的第一个参数是元素,第二个参数是索引,第三个参数被忽略。
  • 一样吧?只不过一个是转化为整数,一个转化为浮点数。

补充:

  • 输出确实是 [1, NaN, NaN]。
  • **原因:**parseInt('1', 0) → 0 表示十进制,返回 1;parseInt('2', 1) → 1 不是有效进制(应为 2~36),返回 NaN;parseInt('3', 2) → 二进制中没有数字 3,返回 NaN。
  • parseFloat 只接收一个参数,所以结果会是 1, 2, 3。
  • parseFloat 只接收一个参数,map 传入的索引会被忽略,所以 parseFloat('1') → 1,parseFloat('2') → 2,parseFloat('3') → 3。

第3题:防抖与节流

我的回答:

  • 防抖:多次触发只在最后一次执行;节流:在一段时间内只执行一次。
  • 搜索框输入用防抖(最后一次提交),滚动加载用节流(固定频率执行)。
  • 实现立即执行版防抖:增加 immediate 参数,第一次触发立即执行,后续延迟。

补充:

  • 防抖和节流的实现细节:
  1. 防抖:每次触发清除定时器,重新计时。立即执行版需要维护一个 called 标志,第一次执行后设置定时器重置标志。
  2. 节流:时间戳版保证第一次立即执行,最后一次可能被忽略;定时器版保证最后一次一定会执行,但可能延迟。可结合两者实现更精确的节流。
  • 实际场景:
  1. 防抖适用于搜索建议、窗口 resize、表单输入验证等。
  2. 节流适用于滚动加载、鼠标移动、按钮快速点击等。

第4题:Set、Map、WeakSet、WeakMap

我的回答:

  • Set 和 Map 的键/值可以是任意类型(包括对象、基本类型)。WeakSet/WeakMap 的键只能是对象,且是弱引用。
  • WeakMap 的弱引用意味着当键对象不再被其他地方引用时,会自动被垃圾回收,适合存储 DOM 元素相关的临时数据,避免内存泄漏。
  • WeakMap 不可遍历(没有 keys()、values()、entries() 等方法)因为随时会回收所以遍历没有意义。

补充:

  • Set 类似数组,成员唯一;Map 类似对象,键可以是任意类型。
  • WeakSet 成员只能是对象,弱引用,不可遍历;WeakMap 键只能是对象,值可以是任意类型,弱引用,不可遍历。
  • 弱引用的意义:防止因 Map 中保存了 DOM 元素引用而导致无法被回收。当 DOM 元素被移除时,WeakMap 中的键会自动消失,无需手动清理。

第5题:ES5 / ES6 继承的区别

我的回答:

  • 本质上都是语法糖,但 ES5 需要手动复制,ES6 用 extends 直接继承。底层实现需补充。
  • ES6 子类可以继承父类的静态方法(static),ES5 需要手动赋值(Child.proto = Parent)。
  • ES6 的 super 必须在 this 前调用,因为 ES6 的 class 有"暂时性死区",必须先调用父类构造函数才能初始化 this。

补充:

  • **底层实现:**ES5 继承通过原型链(Child.prototype = Object.create(Parent.prototype))和构造函数借用(Parent.call(this))实现。ES6 的 class 本质也是基于原型,但语法更清晰。
  • **静态继承:**ES6 中 class Child extends Parent 会自动继承静态方法,即 Child.proto === Parent。ES5 需手动设置Object.setPrototypeOf(Child, Parent) 或直接 Child.proto = Parent。
  • **super 的调用时机:**ES6 的 class 中,子类构造函数必须调用 super() 才能使用 this,因为 ES6 的类在构造函数中不会自动创建 this,而是通过 super() 返回父类的 this 并绑定给子类。这与 ES5 中先创建 this 再修改不同。

今日知识点总结

| 题目 | 核心要点 |
| key 的作用 | 帮助 diff 识别节点,避免状态错乱;避免用 index,用稳定唯一 id |
| map(parseInt) | 理解 parseInt 接收进制参数,map 传入索引导致 NaN |
| 防抖与节流 | 防抖:延迟执行且重置;节流:限制频率;实现需注意 this 和参数 |
| Set/Map/Weak... | 存储任意类型键值;Weak 系列弱引用,不可遍历,防止内存泄漏 |

继承区别 ES5 通过原型 + 构造函数;ES6 class 语法糖,自动继承静态方法,super 必须先调用
相关推荐
AI茶水间管理员1 天前
学习ClaudeCode源码之Agent核心循环
前端·人工智能·后端
挖稀泥的工人1 天前
AI聊天界面的布局细节和打字跟随方法
前端·javascript·面试
竹林8181 天前
从“连接失败”到丝滑登录:我用 ethers.js 连接 MetaMask 的完整踩坑记录
前端·javascript
颜酱1 天前
图片大模型实践:可灵(Kling)文生图前后端实现
前端·javascript·人工智能
木斯佳1 天前
前端八股文面经大全:腾讯CSIG实习面(2026-04-10)·面经深度解析
前端·ai·xss·埋点·实习面经
夏暖冬凉1 天前
npm发布流程(记录遇到的问题)
前端·npm·node.js
XPoet1 天前
AI 编程工程化:Subagent——给你的 AI 员工打造协作助手
前端·后端·ai编程
心连欣1 天前
解锁对象遍历:当字符串遇上for...in循环
前端·javascript
Sestid1 天前
前端Cursor使用指南(后续会更新Claude)
前端·claude·cursor
戴维南1 天前
LangChain 在 Agent 开发中的定位:10 个模块(含代码对比,耳机售后案例)
前端