既然const在JavaScript中创建不可变数组是无用的(我不知道确切的原因),那么创建不可变数组的最佳方法是什么?
在我看来,这个问题与javascript无关,我只是想了解javascript核心的一些行为,我不想要库之类的东西 我试图理解为什么这段代码实际上修改了既然const在JavaScript中创建不可变数组是无用的(我不知道确切的原因),那么创建不可变数组的最佳方法是什么?,javascript,Javascript,在我看来,这个问题与javascript无关,我只是想了解javascript核心的一些行为,我不想要库之类的东西 我试图理解为什么这段代码实际上修改了const originalArray const originalArray = [0, 2, 1, 1, 1]; var newArray = originalArray; var removed = newArray.splice(0,3); console.log(originalArray);//return [ 1, 1 ]
const originalArray
const originalArray = [0, 2, 1, 1, 1];
var newArray = originalArray;
var removed = newArray.splice(0,3);
console.log(originalArray);//return [ 1, 1 ]
但与此同时,这是不可能的:
const originalArray = [];
originalArray = [1];
那么,在没有库的情况下,如何创建一个真正不可变的数组呢?您可以使用它
const arr=Object.freeze([1,2,3]);
控制台日志(arr);
arr[1]=7;
控制台日志(arr)
修改newArray
也修改originalArray
的原因是JavaScript中的变量只是对对象的引用。当您说newArray=originalArray
时,您不是在复制数组,而是在复制引用。因此,当您说newArray.splice(0,3)
时,您是在修改newArray
引用的数组,而originalArray
也引用了该数组
类似地,在JavaScript中,单词const
指的是常量引用,而不是底层对象。也就是说,您可以在const
变量上调用突变方法,如.splice
,而不会出现任何问题。当您尝试使用=
或类似方法重新分配变量时,您会遇到错误
正如其他人所注意到的,Object.freeze(41;
将使其无法修改内部对象,从而实现“不变性”,因为您将无法修改底层对象
例如,如果您执行以下操作:
const originalArray = Object.freeze([1, 2, 3]);
let newArray = originalArray; // you can easily use `const` here, but I don't want to confuse the two concepts
newArray.splice(0, 3); // TypeError: Cannot add/remove sealed array elements
如果您想要阵列的副本,可以在不修改原始阵列的情况下进行修改,
Object.freeze
单独使用将无助于您。您需要“深度复制”数组,这可以通过各种方法完成(很容易通过谷歌搜索,因此我将对它们进行编辑,因为这个答案比预期的要长)。const并不像您所想的那样创建常量变量,它创建了不可变的绑定。如果您先编写const arr=[],然后再编写arr={},就会得到错误。偶数对象。仅冻结顶层。例如:
const x = Object.freeze([1, 2, 3, [3, 4, 5]]);
x[3].push(20);
console.log(x)
您将得到[1,2,3,3,4,5,20]],如果您希望它完全不可变,您必须递归地冻结它,但它会影响性能。
您还可以像这样创建数组的副本并使用新的副本
const x = [1,2,3,4,5]
const y = x.slice(0, x.length)
您是否尝试过对象冻结(arr)?@jornsharpe不是一个重复的问题,我编辑了这个问题以避免混淆。我认为这不是问题主体的正确答案,问题主体是当您修改新数组时,为什么原始数组会受到影响。谢谢@Tamas,但我不理解const的这种行为。为了澄清,如果将示例第二条语句中的
let
替换为const
,则将实现相同的行为。如果您将let
替换为const
并删除对象。冻结
,则允许使用拼接
,其行为将与原始问题中的代码相同。谢谢@River您的解释非常清楚。我认为代替Object.freeze的更好方法是var newArray=originalArray.splice()代码>这是深度复制浅数组的好方法。也就是说,如果元素只是数字或不可变的对象,这将起作用。但是,如果数组中有可变对象并修改单个对象,则它们仍将在原始数组中修改。为了确保您不会意外地创建对同一对象的多个引用,我建议使用lodash。谢谢@Vlaev这绝对是反对对象的一个要点。冻结