redux 中 nextListeners = currentListeners.slice()用来干嘛的?

思否 问答 👍 2 含 AI 优化版

问题

redux 中 nextListeners = currentListeners.slice()用来干嘛的?

在 SegmentFault 查看原问题 →

由大模型辅助整理,保留原意,优化结构与可读性。

问题概述

提问者在阅读 Redux 源码时,看到 nextListeners = currentListeners.slice() 这行代码,想知道为什么要用 slice() 复制一份数组,而不是直接赋值。

涉及技术

JavaScript、Redux、数组方法(slice)、引用类型

期望结果

理解 slice() 在这里的作用,以及它和直接赋值(引用拷贝)的本质区别。

回答

原始回答

2018-03-20

slice等于是一个新的数组,如果直接赋值的话,等于把地址指向。具体的比对看下面两张图。

细节上来说,还是不一样的,比如这种情况。JSON的规范里面是没有function的。

而且slice可以截断大小呀什么的。

AI 优化 · 回答整理

解答思路

currentListeners.slice()(不传参数)会返回一个和原数组内容相同、但引用完全独立的新数组;如果直接写 nextListeners = currentListeners,两个变量会指向同一个数组地址,后续对 nextListeners 的增删操作会同时影响到 currentListeners,这在 Redux 需要保证订阅列表在遍历过程中稳定不变的场景下是不允许的。

详细说明

  • 引用 vs 拷贝:数组和对象是引用类型,直接赋值只是复制了指向同一块内存的地址,并不会创建新的数据;slice() 则是遍历原数组、把每个元素放进一个新数组里返回,因此得到的是两个独立的数组,修改一个不会影响另一个。
  • 为什么 Redux 需要这么做:Redux 在触发 dispatch 通知订阅者时,需要保证“这一次通知遍历的监听器列表”是固定的快照,即使在通知过程中有新的 subscribe/unsubscribe 操作也不能影响到本轮正在执行的遍历,用 slice() 复制出一份独立的 nextListeners 正是为了实现这种隔离。
  • 和 JSON 序列化的关联:这里提到 JSON 规范中没有函数类型,是想说明像 JSON.parse(JSON.stringify(arr)) 这种深拷贝方式对包含函数的数组(监听器本身就是函数)是行不通的,slice()(浅拷贝)反而更适合这种只需要拷贝数组结构本身、不需要深拷贝内部元素的场景。
  • slice 的额外能力slice(start, end) 还可以按下标区间截取数组的一部分,不仅仅是用于全量复制。

小结

currentListeners.slice() 的核心目的是拿到一份独立于原数组的浅拷贝,避免在通知订阅者的过程中,因为直接引用同一个数组而被外部的增删操作影响,这是 Redux 保证订阅机制稳定性的一个经典细节实现。

由大模型辅助整理,保留原意,补充结构与代码格式。

回答转载自 SegmentFault

评论

评论功能即将开放。你也可以通过 邮件GitHub Issue 反馈。