如何强制 JavaScript 深度复制字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31712808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:04:55  来源:igfitidea点击:

How to force JavaScript to deep copy a string?

javascriptgoogle-chromememory-managementgarbage-collection

提问by AffluentOwl

I have some javascript code which looks like this:

我有一些 javascript 代码,如下所示:

var myClass = {
  ids: {}
  myFunc: function(huge_string) {
     var id = huge_string.substr(0,2);
     ids[id] = true;
  }
}

Later the function gets called with some large strings (100 MB+). I only want to save a short id which I find in each string. However, the Google Chrome's substring function (actually regex in my code) only returns a "sliced string" object, which references the original. So after a series of calls to myFunc, my chrome tab runs out of memory because the temporary huge_stringobjects are not able to be garbage collected.

稍后,该函数被一些大字符串(100 MB+)调用。我只想保存我在每个字符串中找到的一个短 ID。但是,谷歌浏览器的子字符串函数(实际上是我代码中的正则表达式)只返回一个引用原始字符串的“切片字符串”对象。因此,在对 进行一系列调用后myFunc,我的 chrome 选项卡内存不足,因为huge_string无法对临时对象进行垃圾回收。

How can I make a copy of the string idso that a reference to the huge_stringis not maintained, and the huge_stringcan be garbage collected?

如何制作字符串的副本,id以便huge_string不维护对 的引用,并且huge_string可以进行垃圾回收?

enter image description here

在此处输入图片说明

采纳答案by AffluentOwl

JavaScript's implementation of ECMAScript can vary from browser to browser, however for Chrome, many string operations (substr, slice, regex, etc.) simply retain references to the original string rather than making copies of the string. This is a known issue in Chrome (Bug #2869). To force a copy of the string, the following code works:

JavaScript 的 ECMAScript 实现可能因浏览器而异,但是对于 Chrome,许多字符串操作(substr、slice、regex 等)只是保留对原始字符串的引用,而不是制作字符串的副本。这是 Chrome 中的一个已知问题(错误 #2869)。要强制复制字符串,请使用以下代码:

var string_copy = (' ' + original_string).slice(1);

This code works by appending a space to the front of the string. This concatenation results in a string copy in Chrome's implementation. Then the substring after the space can be referenced.

此代码通过在字符串前面附加一个空格来工作。这种连接会在 Chrome 的实现中产生一个字符串副本。那么空格后的子串就可以被引用了。

This problem with the solution has been recreated here: http://jsfiddle.net/ouvv4kbs/1/

解决方案的这个问题已在此处重新创建:http: //jsfiddle.net/ouvv4kbs/1/

WARNING: takes a long time to load, open Chrome debug console to see a progress printout.

警告:加载需要很长时间,打开 Chrome 调试控制台查看进度打印输出。

// We would expect this program to use ~1 MB of memory, however taking
// a Heap Snapshot will show that this program uses ~100 MB of memory.
// If the processed data size is increased to ~1 GB, the Chrome tab
// will crash due to running out of memory.

function randomString(length) {
  var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  var result = '';
  for (var i = 0; i < length; i++) {
    result +=
        alphabet[Math.round(Math.random() * (alphabet.length - 1))];
  }
  return result;
};

var substrings = [];
var extractSubstring = function(huge_string) {
  var substring = huge_string.substr(0, 100 * 1000 /* 100 KB */);
  // Uncommenting this line will force a copy of the string and allow
  // the unused memory to be garbage collected
  // substring = (' ' + substring).slice(1);
  substrings.push(substring);
};

// Process 100 MB of data, but only keep 1 MB.
for (var i =  0; i < 10; i++) {
  console.log(10 * (i + 1) + 'MB processed');
  var huge_string = randomString(10 * 1000 * 1000 /* 10 MB */);
  extractSubstring(huge_string);
}

// Do something which will keep a reference to substrings around and
// prevent it from being garbage collected.
setInterval(function() {
  var i = Math.round(Math.random() * (substrings.length - 1));
  document.body.innerHTML = substrings[i].substr(0, 10);
}, 2000);

enter image description here

在此处输入图片说明

回答by Daniel C. Deng

I use Object.assign() method for string, object, array, etc:

我对字符串、对象、数组等使用 Object.assign() 方法:

const newStr = Object.assign("", myStr);
const newObj = Object.assign({}, myObj);
const newArr = Object.assign([], myArr);

Note that Object.assign only copies the keys and their properties values inside an object (one-level only). For deep cloning a nested object, refer to the following example:

请注意, Object.assign 仅复制对象内的键及其属性值(仅限一级)。对于嵌套对象的深度克隆,请参考以下示例:

let obj100 = { a:0, b:{ c:0 } };
let obj200 = JSON.parse(JSON.stringify(obj100));
obj100.a = 99; obj100.b.c = 99; // No effect on obj200

回答by Kyle s

I was getting an issue when pushing into an array. Every entry would end up as the same string because it was referencing a value on an object that changed as I iterated over results via a .next() function. Here is what allowed me to copy the string and get unique values in my array results:

推入数组时遇到问题。每个条目都会以相同的字符串结束,因为它引用了一个对象上的值,当我通过 .next() 函数迭代结果时,该值发生了变化。这是允许我复制字符串并在数组结果中获取唯一值的原因:

while (results.next()) {
  var locationName = String(results.name);
  myArray.push(locationName);
}

回答by nuttybrewer

You can use:

您可以使用:

 String.prototype.repeat(1) 

It seems to work well. Refer the MDN documentation on repeat.

它似乎运作良好。请参阅 上的MDN 文档repeat

回答by Pirijan

not sure how to test, but does using string interpolation to create a new string variable work?

不确定如何测试,但使用字符串插值创建新的字符串变量是否有效?

newString = `${oldString}`

回答by Aragorn

I typically use strCopy = new String (originalStr);Is this not recommended for some reason?

我通常使用strCopy = new String (originalStr);这是否出于某种原因不推荐?