【问题标题】:Push reference of string element in an array in to new array of string将数组中字符串元素的引用推入新的字符串数组
【发布时间】:2018-02-21 18:44:06
【问题描述】:

给定以下代码:

    var old_Array =["One","Two","..."];
    var len = old_Array .length;
    var new_Array =[];
    for(var i=0;i<len;++i)
    {
      new_Array.push(old_Array [i]); // ----- [1]
    }

[1]行之后new_Array被字符串填充。

  1. 每个元素实际上是对字符串元素的引用吗? old_Array, 还是只是复制每个字符串元素?
  2. javascript 解释器/编译器是否优化行 -[1] 通过 推送old_Array中每个字符串元素的引用?

【问题讨论】:

  • 只通过引用传递对象,复制字符串等原语。
  • @PatrickEvans 感谢您的快速回复。但是 javascript 引擎是否优化了该代码行?因为该字符串对象的内存分配已经存在于 old_Array 中......我们可以传达我们需要在那里进行优化的编译器......而不是对每个元素进行深拷贝或浅拷贝
  • 想想old_Array是否有相当数量的字符串元素,会发生太多的复制操作。

标签: javascript arrays performance optimization


【解决方案1】:

第一个问题的答案:每个元素只是旧数组中每个字符串元素的一个副本。 如果数组包含对象引用,则将引用复制到新数组中。 (在这种情况下,字符串和数字等原始类型是按值复制的。)

回答第二个问题:不,javascript 解释器不会通过推送 old_Array 中每个字符串元素的引用来优化第 [1] 行。

复制数组的更快更好的方法是:

var new_Array = old_Array.slice();

它克隆旧数组并返回对新数组的引用。

【讨论】:

  • 谢谢。是的 slice() 使用克隆的概念。当您考虑每两个数组的基数时,认为您希望在 new_Array 中包含 old_array 元素的一部分,出于表示目的,我们可以new_Array 结构,如果我们在旧数组中有 100000 个字符串元素,并且当我们不得不只使用其中的 5000 个而不是克隆时,我们创建新的数组结构,该结构适合 5000 个与旧数组中已经存在的数据,因此我们可以代替执行 5000 个复制操作通过引用已存在于旧数组中的数据 v 的直接内存位置。
  • @Buddhika 在这种情况下,您必须确保旧数组不会被删除。此外,如果元素大小更小,将元素复制到新数组会更有意义。如果数组元素的大小太大,那么通过引用访问它们是最佳的。
【解决方案2】:

有趣的问题。问题是字符串是不可变的,这意味着一旦将它们写入内存,就无法更改。所以当你喜欢的时候

var s2 = s.substr(0, 3);

s2 现在是一个新字符串,但它不会复制到新的内存位置,而是表示为s 中的一个范围。因此,根据您的问题,从字符串数组中复制字符串不应为新字符串分配额外的内存。但是,当不再需要包含原始字符串的数组时,GC 应该足够聪明地决定从该数组分配的内存中删除哪些项并保留在该数组中。

我猜实现会因 JS 引擎而异。这里有一些关于 MDN 的信息。

【讨论】:

  • 感谢您的关心和解答。
  • 顺便说一句 Redu,只要 s2 不会改变,它可以表示为 s 的范围,但是如果我们假设 javascript 解释器/编译器具有深度代码分析和运行时检查它可以将 s2 优化为 s 的范围表示,而不是使用新的内存分配的新字符串,但是如果它检测到对 s2 的任何修改,它会改为分配新的内存吗?
  • @Buddhika s2.. 会发生什么样的变化?记住s2 也是不可变的。唯一可能发生的事情是在没有更多代码引用它时被垃圾收集器 (GC) 删除。
  • 现在明白了,伙计..你的正确,我之前错过了一点。 s2 只是 C/C++ 指针/引用之类的东西。不是吗?
猜你喜欢
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多