Являются ли строки JavaScript неизменяемыми? Нужен ли мне «строитель строк» ​​в JavaScript? - PullRequest
208 голосов
/ 09 сентября 2008

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

Ответы [ 10 ]

272 голосов
/ 18 января 2011

Они неизменны. Вы не можете изменить символ в строке с чем-то вроде 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

43 голосов
/ 09 сентября 2008

из книги носорогов :

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

20 голосов
/ 09 сентября 2008

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

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

В JavaScript нет StringBuilder.

2 голосов
/ 09 сентября 2018

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

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

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

Неизменный означает, что:

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

var immutableString = "Hello";

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

immutableString = immutableString + "World";

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

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

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

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

Значение типа 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 является изменяемым, но значение строкового типа (тип примитива), которое он содержит, является неизменным.

2 голосов
/ 18 августа 2015

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

Пример:

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

var other= statement.slice(2, 10); // new string
1 голос
/ 02 августа 2018

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

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

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

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

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

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

противоположно объектам :

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

1 голос
/ 09 сентября 2008

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

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

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

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

0 голосов
/ 09 сентября 2008

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

0 голосов
/ 09 сентября 2008

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

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