如何创建一个不被JavaScript中的引用修改的常量数组?
我很惊讶javascript中会出现这种情况,但当我开发算法时,我注意到了这一点 当我把“mt”数组放在“wm”常量中,我在“mt”数组中改变一个值,这个值在“wm”数组中改变。为什么会这样?我怎样才能保证这一切不会发生如何创建一个不被JavaScript中的引用修改的常量数组?,javascript,node.js,arrays,Javascript,Node.js,Arrays,我很惊讶javascript中会出现这种情况,但当我开发算法时,我注意到了这一点 当我把“mt”数组放在“wm”常量中,我在“mt”数组中改变一个值,这个值在“wm”数组中改变。为什么会这样?我怎样才能保证这一切不会发生 我这样问是因为在我看来,“wm”应该包含一个“mt”数组的副本,除非我直接修改它,否则不应该更改。当您将wm标记为mt时,它不会复制数组,它会创建对该数组的引用,因此当您修改原始数组时,它也会修改wm 你可以通过使用 因此: 变量不直接包含对象(包括数组),它们包含对内存中其
我这样问是因为在我看来,“wm”应该包含一个“mt”数组的副本,除非我直接修改它,否则不应该更改。当您将
wm
标记为mt
时,它不会复制数组,它会创建对该数组的引用,因此当您修改原始数组时,它也会修改wm
你可以通过使用
因此:
变量不直接包含对象(包括数组),它们包含对内存中其他位置的对象的引用。因此,你从以下几点开始: +−−−−−−−−−−−−+ mt:Ref55162−−−−−−−−−−−>| (array) | +−−−−−−−−−−−−+ | 0: "hola" | | 1: "adios" | +−−−−−−−−−−−−+ (该Ref55162值仅用于说明;在JavaScript代码中,您永远看不到对象引用的实际值。) 如果要制作阵列的副本,可以使用多种选项:
slice
:const wm=mt.slice()代码>
Array.from
:const wm=Array.from(mt)代码>
constwm=[…mt]代码>
concat
:[].concat(mt)
slice
创建词法环境对象,但在实践中,实现并不总是需要创建这些对象,并尽可能避免这些对象。)
可能值得指出的是,如果您有一个包含对象引用的数组,那么就像wd=mt
,以上所有内容都会为您提供一个包含引用副本的新数组。因此,如果你有:
const a = [{value: 1}, {value: 2}];
const b = a.slice();
…现在a
和b
是不同的数组,但两个数组都包含对相同两个对象的引用:
+−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+
a:Ref14785−−−−−>| (array) | | |
+−−−−−−−−−−−−−+ \ +−−−−−−−−−−+ |
| 0: Ref55463 |−−−+−>| (object) | |
| 1: Ref16839 |−−+ +−−−−−−−−−−+ |
+−−−−−−−−−−−−−+ | | value: 1 | |
| +−−−−−−−−−−+ |
| |
\ +−−−−−−−−−−+ |
+−>| (object) | |
/ +−−−−−−−−−−+ |
| | value: 2 | |
| +−−−−−−−−−−+ |
+−−−−−−−−−−−−−+ | |
b:Ref98464−−−−−>| (array) | | |
+−−−−−−−−−−−−−+ | |
| 0: Ref55463 |−−|−−−−−−−−−−−−−−−−−+
| 1: Ref16839 |−−+
+−−−−−−−−−−−−−+
map
为数组中的每个条目调用回调函数,并根据返回值构建新数组{…obj}
将自己的可枚举属性从对象复制到新对象中
或者,如果a
是数组的数组,则可以执行以下操作:
const b = a.map(array => array.slice());
(继续。如果内部对象或数组包含对象、引用,则…)
如果你想一路抄袭(深度抄袭),这个问题的答案可能很有用:
或者,如果希望阵列不可修改,可以对其使用
freeze
:
Object.freeze(mt);
那么您就不能更改它。请将代码、错误消息、标记等以文本形式发布,而不是以文本图片的形式发布。原因:变量“wm”和“mt”都引用了最终存储的相同数据。文档说明您不能重新声明或分配常量变量,您是在这里执行的吗?不,您在数组中修改了一个变量,
[].concat(mt)
?@Ifaruki-当然,您也可以这样做。我不喜欢它,因为它是一次性数组,但这很可能会得到优化(就像我的spread示例中的迭代器对象一样)。如何获得关于javascript的超深入知识?非常感谢@t.J.Crowder。这正是我要找的。我已经证明了这一点,当我使用const wm=mt.slice()时,它对我很有效代码>@Teemu-Hmmm。是的,这可能值得一提(尽管我会对“预期”;-)吹毛求疵)。
const b = a.map(obj => ({...obj}));
const b = a.map(array => array.slice());
Object.freeze(mt);