第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人工智能+电脑小能手7 小时前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
ZC跨境爬虫8 小时前
跟着 MDN 学CSS day_39:(Flexbox 弹性盒子核心机制)
前端·css·ui·html·tensorflow
小陈同学呦8 小时前
前端如何处理订单状态导航的数据竞态问题
前端·javascript
喵个咪9 小时前
GoWind Toolkit 前端代码生成|Vue3(ElementPlus/Vben)、React(AntDesign)全自动一键生成教程
前端·vue.js·react.js
Cosolar9 小时前
从零写一个 Attention Is All You Need
人工智能·面试·架构
摆烂大大王10 小时前
玩转 OpenClaw:用 TaskFlow + Heartbeat 打造自动化工作流
前端·人工智能·自动化
zhangxingchao10 小时前
AI 大模型核心六:量化、Workflow 与 Agent、多轮 RAG
前端·人工智能·后端
梦想的颜色10 小时前
TypeScript 完全指南(上):从零开始掌握类型系统
前端·typescript
之歆11 小时前
Day01_ES6+ 专业指南:从基础到实战的现代JavaScript开发(下)
前端·javascript·es6
_日拱一卒11 小时前
LeetCode:207课程表
java·数据结构·算法·leetcode·职场和发展