Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何创建一个不被JavaScript中的引用修改的常量数组?_Javascript_Node.js_Arrays - Fatal编程技术网

如何创建一个不被JavaScript中的引用修改的常量数组?

如何创建一个不被JavaScript中的引用修改的常量数组?,javascript,node.js,arrays,Javascript,Node.js,Arrays,我很惊讶javascript中会出现这种情况,但当我开发算法时,我注意到了这一点 当我把“mt”数组放在“wm”常量中,我在“mt”数组中改变一个值,这个值在“wm”数组中改变。为什么会这样?我怎样才能保证这一切不会发生 我这样问是因为在我看来,“wm”应该包含一个“mt”数组的副本,除非我直接修改它,否则不应该更改。当您将wm标记为mt时,它不会复制数组,它会创建对该数组的引用,因此当您修改原始数组时,它也会修改wm 你可以通过使用 因此: 变量不直接包含对象(包括数组),它们包含对内存中其

我很惊讶javascript中会出现这种情况,但当我开发算法时,我注意到了这一点

当我把“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)

  • 请注意#2-#4理论上涉及临时对象,但如果此代码处于性能关键区域,则这些临时对象可能会得到优化#1不涉及任何临时对象。(好的,即使是最后一个,理论上规范描述了为调用
    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);