Являются ли строки JavaScript неизменяемыми?Нужен ли мне «построитель строк» ​​в JavaScript?

StackOverflow https://stackoverflow.com/questions/51185

  •  09-06-2019
  •  | 
  •  

Вопрос

Использует ли Javascript неизменяемые или изменяемые строки?Нужен ли мне «строитель строк»?

Это было полезно?

Решение

Они неизменны.Вы не можете изменить символ внутри строки чем-то вроде var myString = "abbdef"; myString[2] = 'c'.Методы манипуляции со строками, такие как trim, slice вернуть новые строки.

Аналогично, если у вас есть две ссылки на одну и ту же строку, изменение одной не повлияет на другую.

let a = b = "hello";
a = a + " world";
// b is not affected

Однако я всегда слышал то, что Эш упоминал в своем ответе (что использование Array.join быстрее для конкатенации), поэтому я хотел протестировать различные методы конкатенации строк и самый быстрый способ абстрагирования в StringBuilder.Я написал несколько тестов, чтобы проверить, правда ли это (это не так!).

Я считал, что это будет самый быстрый способ, хотя продолжал думать, что добавление вызова метода может замедлить его...

function StringBuilder() {
    this._array = [];
    this._index = 0;
}

StringBuilder.prototype.append = function (str) {
    this._array[this._index] = str;
    this._index++;
}

StringBuilder.prototype.toString = function () {
    return this._array.join('');
}

Вот тесты скорости производительности.Все три из них создают гигантскую строку, состоящую из конкатенирующих "Hello diggity dog" сто тысяч раз в пустую строку.

Я создал три типа тестов

  • С использованием Array.push и Array.join
  • Использование индексации массива, чтобы избежать Array.push, затем используя Array.join
  • Прямая конкатенация строк

Затем я создал те же три теста, абстрагировав их в StringBuilderConcat, StringBuilderArrayPush и StringBuilderArrayIndex http://jsperf.com/string-concat-without-sringbuilder/5 Пожалуйста, сходите туда и проведите тесты, чтобы мы могли получить хороший образец.Обратите внимание, что я исправил небольшую ошибку, из-за которой данные для тестов были стерты. Я обновлю таблицу, как только будет достаточно данных о производительности.Идти к http://jsperf.com/string-concat-without-sringbuilder/5 для старой таблицы данных.

Вот несколько цифр (Последнее обновление в Ma5rch 2018), если вы не хотите идти по ссылке.Число на каждом тесте — 1000 операций в секунду (выше, лучше)

| Browser          | Index | Push | Concat | SBIndex | SBPush | SBConcat |
---------------------------------------------------------------------------
| Chrome 71.0.3578 | 988   | 1006 | 2902   | 963     | 1008   | 2902     |
| Firefox 65       | 1979  | 1902 | 2197   | 1917    | 1873   | 1953     |
| Edge             | 593   | 373  | 952    | 361     | 415    | 444      |
| Exploder 11      | 655   | 532  | 761    | 537     | 567    | 387      |
| Opera 58.0.3135  | 1135  | 1200 | 4357   | 1137    | 1188   | 4294     | 

Выводы

  • В настоящее время все вечнозеленые браузеры хорошо справляются с конкатенацией строк. Array.join помогает только IE 11

  • В целом Opera самая быстрая, в 4 раза быстрее, чем Array.join.

  • Firefox является вторым и Array.join лишь немного медленнее в FF, но значительно медленнее (в 3 раза) в Chrome.

  • Chrome занимает третье место, но объединение строк в 3 раза быстрее, чем Array.join.

  • Создание StringBuilder, похоже, не слишком сильно влияет на производительность.

Надеюсь, кто-то еще найдет это полезным

Другой тестовый пример

Поскольку @RoyTinker решил, что мой тест ошибочен, я создал новый случай, который не создает большую строку путем объединения одной и той же строки, а использует разные символы для каждой итерации.Конкатенация строк по-прежнему казалась более быстрой или такой же быстрой.Давайте запустим эти тесты.

Я предлагаю всем продолжать думать о других способах проверки этого и не стесняться добавлять новые ссылки на различные тестовые примеры ниже.

http://jsperf.com/string-concat-without-sringbuilder/7

Другие советы

из книга о носороге:

В JavaScript строки являются неизменными объектами, что означает, что персонажи внутри них не могут быть изменены и что любые операции на строках фактически создают новые строки.Строки присваиваются ссылкой, а не по значению.В целом, когда объект назначается ссылкой, изменение, внесенное в объект через одну ссылку, будет видно во всех других ссылках на объект.Однако, поскольку строки нельзя изменить, вы можете иметь несколько ссылок на строковый объект и не беспокоиться о том, что строковое значение изменится без вашего знания.

Совет по производительности:

Если вам нужно объединить большие строки, поместите части строки в массив и используйте Array.Join() метод для получения общей строки.Это может быть во много раз быстрее при объединении большого количества строк.

Здесь нет StringBuilder в JavaScript.

Строки неизменяемы – они не могут измениться, мы можем только создавать новые струны.

Пример:

var str= "Immutable value"; // it is immutable

var other= statement.slice(2, 10); // new string

Значение строкового типа является неизменяемым, но Объект String, созданный с помощью конструктора String(), является изменяемым, поскольку это объект, и к нему можно добавлять новые свойства.

> var str = new String("test")
undefined
> str
[String: 'test']
> str.newProp = "some value"
'some value'
> str
{ [String: 'test'] newProp: 'some value' }

При этом, хотя вы и можете добавлять новые свойства, вы не можете изменить уже существующие свойства.

Скриншот теста в консоли Chrome

В заключение, 1.все значения строкового типа (примитивный тип) являются неизменяемыми.2.Объект String является изменчивым, но содержащееся в нем значение строкового типа (примитивный тип) является неизменяемым.

Просто чтобы прояснить для простых умов, таких как мой (из МДН):

Неизменяемые — это объекты, состояние которых не может быть изменено после создания объекта.

Строка и числа неизменяемы.

Неизменяемость означает, что:

Вы можете сделать так, чтобы имя переменной указывало на новое значение, но предыдущее значение все равно будет храниться в памяти.Отсюда и необходимость вывоза мусора.

var immutableString = "Hello";

// В приведенном выше коде создается новый объект со строковым значением.

immutableString = immutableString + "World";

// Теперь мы добавляем «World» к существующему значению.

Похоже, мы изменяем строку immutableString, но это не так.Вместо:

При добавлении «immutableString» к строковому значению происходят следующие события:

  1. Существующее значение «immutableString» извлекается.
  2. «Мир» добавляется к существующему значению «immutableString».
  3. Результирующее значение затем выделяется в новый блок памяти.
  4. Объект immutableString теперь указывает на вновь созданное пространство памяти.
  5. Ранее созданное пространство памяти теперь доступно для сбора мусора.

Что касается вашего вопроса (в комментарии к ответу Эша) о StringBuilder в ASP.NET Ajax, эксперты, похоже, не согласны с этим.

Кристиан Венц говорит в своей книге Программирование ASP.NET AJAX (О'Рейли), что «этот подход не оказывает какого-либо измеримого влияния на память (фактически, реализация кажется немного медленнее, чем стандартный подход)».

С другой стороны, Галло и др. говорят в своей книге: ASP.NET AJAX в действии (Мэннинг) что «Когда количество объединяемых строк больше, построитель строк становится важным объектом, позволяющим избежать значительного падения производительности».

Я думаю, вам придется провести собственное тестирование, и результаты могут также отличаться в разных браузерах.Однако даже если это не улучшит производительность, его все равно можно считать «полезным» для программистов, привыкших писать код с помощью StringBuilders на таких языках, как C# или Java.

Это поздний пост, но среди ответов я не нашел хорошей цитаты из книги.

Вот определенная выдержка из надежной книги:

Строки являются неизменяемыми в ECMAScript, а это означает, что после их создания их значения не могут измениться.Чтобы изменить строку, хранящуюся в переменной, исходную строку необходимо уничтожить, а переменную заполнить другой строкой, содержащей новое значение... —Профессиональный JavaScript для веб-разработчиков, 3-е изд., стр. 43.

Теперь ответ, который цитирует отрывок из Rhino Book, прав в отношении неизменности строки, но неправильно говоря: «Строки присваиваются ссылкой, а не по значению». (Вероятно, они изначально предназначались для того, чтобы поставить слова противоположным образом).

Заблуждение «ссылка/значение» разъясняется в главе «Профессиональный JavaScript», глава «Примитивные и ссылочные значения»:

Пять примитивных типов...[являются]:Неопределенное, пустое, логическое, число и строка.Говорят, что доступ к этим переменным осуществляется по значению, поскольку вы манипулируете фактическим значением, хранящимся в переменной. —Профессиональный JavaScript для веб-разработчиков, 3-е изд., стр.85.

это против объекты:

Когда вы манипулируете объектом, вы на самом деле работаете над ссылкой на этот объект, а не над самим объектом.По этой причине говорят, что такие значения доступны по ссылке.—Профессиональный JavaScript для веб-разработчиков, 3-е изд., стр.85.

Строки JavaScript действительно неизменяемы.

Строки в Javascript неизменяемы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top