Подтвердить что ты не робот

Как заставить JavaScript полностью скопировать строку?

У меня есть код javascript, который выглядит следующим образом:

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

Позже функция вызывается с несколькими большими строками (100 МБ +). Я хочу только сохранить короткий идентификатор, который я нахожу в каждой строке. Однако функция подстроки Google Chrome (фактически регулярное выражение в моем коде) возвращает только объект "нарезанной строки", который ссылается на оригинал. Поэтому после серии вызовов myFunc моя хромированная вкладка заканчивается из-за нехватки памяти, потому что временные объекты huge_string не могут быть собраны в мусор.

Как я могу сделать копию строки id, чтобы ссылка на huge_string не поддерживалась, а huge_string можно было собрать мусор?

введите описание изображения здесь

4b9b3361

Ответ 1

JavaScript-версия ECMAScript может варьироваться от браузера к браузеру, однако для Chrome многие строковые операции (substr, slice, regex и т.д.) просто сохраняют ссылки на исходную строку, а не создают копии строки. Это известная проблема в Chrome (Ошибка # 2869). Чтобы заставить копию строки, работает следующий код:

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

Этот код работает, добавив пробел в начало строки. Эта конкатенация приводит к строковой копии в реализации Chrome. Затем можно указать ссылку под пространством.

Эта проблема с решением была воссоздана здесь: http://jsfiddle.net/ouvv4kbs/1/

ВНИМАНИЕ: для загрузки требуется много времени, откройте консоль отладки 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);

введите описание изображения здесь

Ответ 2

Я использую метод Object.assign() для строки, объекта, массива и т. Д.:

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

Обратите внимание, что 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

Ответ 3

У меня возникла проблема при загрузке в массив. Каждая запись заканчивалась бы как одна и та же строка, потому что она ссылалась на значение объекта, которое изменилось, когда я перебрал результаты с помощью функции .next(). Вот что позволило мне скопировать строку и получить уникальные значения в результатах моего массива:

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

Ответ 4

Вы можете использовать:

 String.prototype.repeat(1) 

Кажется, это хорошо работает. Обратитесь к документации MDN на repeat.