第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 必须先调用
相关推荐
xkxnq1 小时前
第六阶段:Vue生态高级整合与优化(第96天) Vue i18n优化:语言包按需加载+缓存当前语言+避免页面刷新失效
前端·vue.js·缓存
Dxy12393102161 小时前
Ajax如何发送列表数据
前端·ajax·okhttp
C澒1 小时前
微前端容器标准化 —— 公共能力篇:通用跨框架通信能力
前端·架构
程序员buddha1 小时前
Java面试八股文基础篇
java·开发语言·面试
资讯第一线2 小时前
RAD Studio 13.1 [DELPHI 13.1] [官方原版IOS] 下载
前端
橘子编程2 小时前
CSS 全栈指南:从基础到 2025 新特性
前端·css·chrome·tensorflow·less·css3·html5
不会写DN2 小时前
从依赖到自主:手写一个 ICO 文件转换器
前端·javascript·typescript·node.js