Javascript 不变性和本地数组

Javascript immutability and local array

更新:我现在明白,在下面的代码中,我在遍历 pagedData.

时改变了 aggregateData 数组
  1. 我想知道如何在不突变的情况下做到这一点?
  2. 一般来说,当尝试在代码库中尽可能多地尊重不变性时,改变本地定义的数组(就像我在我的示例中所做的那样)时会有多少担忧?由于数组是在本地定义的,我想知道改变数组真的会产生负面影响吗?
const pagedData = [
  {data: ["val1", "val2"], nextPage: 2},
  {data: ["val3", "val4"], nextPage: 3},
  {data: ["val5", "val6"]}
];

const aggregator = () => {
  let aggregateData = [];
  let hasNextPage;
  let page = 1;

  do {
    const { data, nextPage } = pagedData[page - 1];
    aggregateData = [...aggregateData, ...data];
    page = nextPage;
    hasNextPage = nextPage;
  } while (hasNextPage);

  return aggregateData;
}

console.log(aggregator());

/* output: ["val1", "val2", "val3", "val4", "val5", "val6"] */

不可变性有时有助于减少难以捕获的错误,但这可能并不总是必需的或不是理想情况。

什么是不变性?

不改变值是指不变性。在Javascript、array and objects are mutable.

不变性示例:

let arr = ['John', 'Alice'];

// Adding element is mutating
arr.push('Oliver');

// Updating data is mutating
arr[1] = 'Lily'

很多其他函数可以改变这个数组。更多here

  • 内复制
  • 填充
  • 流行
  • 推送
  • 反转
  • 转变
  • 排序
  • 拼接
  • 取消移位

另请注意,将数组或对象定义为 const 并不能保证不变性。 例如:

const obj = {
  name: 'foo'
}
// update name
obj.name = 'bar';

console.log(obj);

const arr = ['foo'];

// push new item
arr.push('bar');

console.log(arr);

现在回答你的问题。传播运算符什么时候可以变异,什么时候不能变异?

如果我们有这个数组,只要这个数组中的任何数据发生变化,它就会失去不变性。

let arr = ['Obito', 'Sasuke'];
let sameReferenceArray = arr;

console.log(arr === sameReferenceArray);

// here the original array did not mutate 
let newArray = [...arr, 'Madara'];
console.log(arr === sameReferenceArray);

// but here it did mutate as the new array is assigned back to arr
arr = [...arr, 'Madara'];
console.log(arr === sameReferenceArray);

还有更多关于哪些方法会发生变异,哪些不会发生变异的示例,您会随着时间的推移学习它们。

编辑 突变如何产生负面影响?

// simple example demostrating negative impact of mutataion
const obj = { name: "foo" };
const arr = [obj, obj]

console.log(arr);

// Mutating first element
arr[0].name = "bar";

console.log("Contents after mutation", arr);

如您所见,我们最终更新了两个对象,即使我们更新了索引 0 处的对象。
现在我将传播和变异:

const obj = { name: "foo" };
const arr = [{...obj}, {...obj}]

console.log(arr);

// Mutating first element
arr[0].name = "bar";

console.log("Contents after mutation", arr);

现在只有预期的元素发生了变异。


这还有很多。一般来说,如果您已经开始学习,不可变性应该不是一个非常大的问题。但知道它肯定有帮助。

例如 React 状态不应该被改变 (reason)

最后,关于如何更新 `aggregatedData'。

const aggregator = () => {
  let aggregateData = [];
  let hasNextPage;
  let page = 1;

  do {
    const { data, nextPage } = pagedData[page - 1];
    aggregateData = [...aggregateData, ...data];
    page = nextPage;
    hasNextPage = nextPage;
  } while (hasNextPage);

  return aggregateData;
}

由于您将数据添加到数组中,因此您最终还是会对其进行变异。您可以执行 spreadpush 或其他操作。这一切都很好,因为数组是在函数内部本地创建并返回的。

示例,它可能是一个问题:

const aggregator = (aggregateData) => {
  for (const i = 0; i < 5; i++)
    aggregateData = [...aggregateData, i];

  return aggregateData;
}

const example = () => {
  let arr = [];
  let data = aggregator(arr);
  // if this array is passed to couple other functions too and mutated then it will get hard to track. This is where the issue can occur

}

example();