![](/img/trans.png)
[英]In JavaScript, Why constant String cannot be modified but constant array can be modified
[英]How to create a constant array that is not modified by its reference in JavaScript?
变量不直接包含对象(包括数组),它们包含对 memory 中其他地方的那些对象的引用。 所以你开始:
+−−−−−−−−−−−−+ mt:Ref55162−−−−−−−−−−−>| (array) | +−−−−−−−−−−−−+ | 0: "hola" | | 1: "adios" | +−−−−−−−−−−−−+
然后当你做const wm = mt;
,您只是在复制参考; 两个变量(常量)都指向同一个数组:
mt:Ref55162−−−−−+ | | +−−−−−−−−−−−−+ +−−−−−>| (array) | | +−−−−−−−−−−−−+ | | 0: "hola" | wm:Ref55162−−−−−+ | 1: "adios" | +−−−−−−−−−−−−+
(该 Ref55162 值仅用于说明;您永远不会在 JavaScript 代码中看到 object 引用的实际值。)
如果你想复制一个数组,你有多种选择:
slice
: const wm = mt.slice();
Array.from
: const wm = Array.from(mt);
扩展符号: const wm = [...mt];
concat
: [].concat(mt)
请注意,#2 - #4 理论上涉及临时对象,但如果此代码位于性能关键区域,则这些临时对象可能会被优化掉。 #1 不涉及任何临时对象。 (好吧,即使是最后一个,理论上规范描述了创建一个词法环境 object 来调用slice
,但在实践中,实现并不总是必须逐字创建这些对象并尽可能避免它。)
值得指出的是,如果您有一个包含 object 引用的数组,那么就像wd = mt
一样,以上所有内容都会为您提供一个包含引用副本的新数组。 因此,如果您有:
const a = [{value: 1}, {value: 2}];
const b = a.slice();
...现在a
和b
是不同的 arrays,但 arrays 都包含对相同两个对象的引用:
+−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−+ a:Ref14785−−−−−>| (array) | | | +−−−−−−−−−−−−−+ \ +−−−−−−−−−−+ | | 0: Ref55463 |−−−+−>| (object) | | | 1: Ref16839 |−−+ +−−−−−−−−−−+ | +−−−−−−−−−−−−−+ | | value: 1 | | | +−−−−−−−−−−+ | | | \ +−−−−−−−−−−+ | +−>| (object) | | / +−−−−−−−−−−+ | | | value: 2 | | | +−−−−−−−−−−+ | +−−−−−−−−−−−−−+ | | b:Ref98464−−−−−>| (array) | | | +−−−−−−−−−−−−−+ | | | 0: Ref55463 |−−|−−−−−−−−−−−−−−−−−+ | 1: Ref16839 |−−+ +−−−−−−−−−−−−−+
如果您想复制这些对象,则必须故意这样做,例如:
const b = a.map(obj => ({...obj}));
map
为数组中的每个条目调用回调,并根据返回值构建一个新数组; {...obj}
将自己的可枚举属性从 object 复制到新的 object 中。
或者如果a
是 arrays 的数组,您可以这样做:
const b = a.map(array => array.slice());
(这继续。如果内部 object 或数组包含 object,则引用,然后...)
如果您想一直复制(“深度”复制),这个问题的答案可能很有用:在 JavaScript 中深度克隆 object 的最有效方法是什么?
或者,如果您希望数组不可修改,您可以对其使用freeze
:
Object.freeze(mt);
那你根本改变不了。
当您将wm
分配给mt
时,它不会复制数组,而是创建对该数组的引用,因此当您修改原始数组时,它也会修改wm
。
你可以通过使用Array.prototype.slice来解决这个问题。
所以:
const wm = mt.slice();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.