【问题标题】:does array.filter() creates a new array?array.filter() 会创建一个新数组吗?
【发布时间】:2021-01-04 12:55:46
【问题描述】:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
按照文档所述 filter() 方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

根据文档下面的脚本应该控制台Learning
console.log(Arr[0].name) // 学习

var Arr = [{name:'Learning'},{name:'Questing'}]
var Arr2 = Arr.filter(it=> true);
Arr2[0].name = 'Stack-Over-Flow';
console.log(Arr[0].name) // Stack-Over-Flow

【问题讨论】:

  • 它会创建一个新数组,但不会对数组内容进行深度复制。对象在原始数组和新数组中都被引用。
  • Arr2.pop() 中的新数组不会影响Arr。对象还是一样的Arr[0] === Arr2[0]

标签: javascript arrays


【解决方案1】:

是的,.filter 创建了一个新数组,但 新数组 是唯一创建的新结构。数组的项目保持不变。

使用您的代码,过滤后,您有一个 new 数组,其中包含 2 个项目,其中两个项目都是对原始中的 相同对象 的引用大批。因此,对新数组中的一个对象进行变异会导致旧数组中的对象发生变异,因为它们指向内存中的同一个对象。

如果你想避免这种情况,你必须先对数组进行深度克隆,也许使用

const Arr2 = Arr
  .filter(it => true)
  .map(obj => ({ ...obj }));

【讨论】:

  • @IshwarChandraTiwari 这正是这个答案在第一行所说的
  • 确实创建了一个新数组(就像我的回答在第一句话中所说) - 但新数组是唯一创建的新结构
  • @IshwarChandraTiwari 您必须区分 new array(项目的容器)和 new objects(进入容器的项目)。 .filter() 创建前者,而不是后者。
  • 它不会修改旧数组,它会修改一个同时存在于旧数组和新数组中的对象
  • @IshwarChandraTiwari 它修改了旧数组中的 objects。它不会修改旧数组本身 - 旧数组仍然包含相同的 2 个项目。数组容器是新的,旧数组中包含的项仍保留在旧数组中,但相同的项也会放入新数组中,因此更改新数组中的一项会导致旧数组看起来不同好吧 - 尽管旧的数组容器没有改变。
【解决方案2】:

.filter 确实创建了一个新数组,但是从旧数组中筛选出的元素的数组。

虽然旧数组中的元素是对象,但新数组仍然保留其引用。为避免这种情况,您可以使用.map 克隆该元素以获取全新参考

var Arr = [{name:'Learning'},{name:'Questing'}]
var Arr2 = Arr.filter(it=> true).map(el => ({...el}));
Arr2[0].name = 'Stack-Over-Flow';
console.log(Arr[0].name)

【讨论】:

  • 所以 arr.filter 持有引用?
  • @IshwarChandraTiwari 对象值总是它的引用。如果你这样做 a = {foo: 1}; b = a 你仍然有 one 对象,但它有两个不同的变量。 b.bar = 2; console.log(a) 仍将打印 {foo: 1, bar: 2}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
  • 2011-02-15
  • 2020-06-10
  • 2014-01-04
  • 1970-01-01
相关资源
最近更新 更多