Javascript 不变性和本地数组
Javascript immutability and local array
更新:我现在明白,在下面的代码中,我在遍历 pagedData
.
时改变了 aggregateData
数组
- 我想知道如何在不突变的情况下做到这一点?
- 一般来说,当尝试在代码库中尽可能多地尊重不变性时,改变本地定义的数组(就像我在我的示例中所做的那样)时会有多少担忧?由于数组是在本地定义的,我想知道改变数组真的会产生负面影响吗?
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;
}
由于您将数据添加到数组中,因此您最终还是会对其进行变异。您可以执行 spread
或 push
或其他操作。这一切都很好,因为数组是在函数内部本地创建并返回的。
示例,它可能是一个问题:
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();
更新:我现在明白,在下面的代码中,我在遍历 pagedData
.
aggregateData
数组
- 我想知道如何在不突变的情况下做到这一点?
- 一般来说,当尝试在代码库中尽可能多地尊重不变性时,改变本地定义的数组(就像我在我的示例中所做的那样)时会有多少担忧?由于数组是在本地定义的,我想知道改变数组真的会产生负面影响吗?
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;
}
由于您将数据添加到数组中,因此您最终还是会对其进行变异。您可以执行 spread
或 push
或其他操作。这一切都很好,因为数组是在函数内部本地创建并返回的。
示例,它可能是一个问题:
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();