Строки JavaScript неизменяемы? Нужен ли мне "построитель строк" ​​в JavaScript?

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

Ответ 1

Они неизменны. Вы не можете изменить символ в строке с помощью чего-то вроде var myString = "abbdef"; myString[2] = 'c' 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" из конкатенации "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 для получения старой таблицы данных.

Вот некоторые цифры от 21 февраля 2013 года, если вы не хотите переходить по ссылке. Число в каждом тесте в операциях/секунду (чем выше, тем лучше)

| Browser          | Index | Push | Concat | SBIndex | SBPush | SBConcat |
---------------------------------------------------------------------------
| Chrome 24.0.1312 | 83    | 87   | 702    | 69      | 87     | 165      |
| Chrome 25.0.1364 | 43    | 47   | 620    | 42      | 42     | 68       |
| Firefox 10.0.10  | 164   | 164  | 533    | 164     | 16     | 421      |
| Firefox 19.0     | 70    | 70   | 259    | 70      | 70     | 186      |
| Exploder 7.0     | 51    | 33   | 58     | 31      | 37     | 45       |
| Exploder 8.0     | 48    | 30   | 58     | 30      | 36     | 36       |
| Exploder 9.0     | 87    | 64   | 95     | 61      | 61     | 61       |
| Opera 12.14      | 125   | 154  | 66     | 106     | 137    | 63       | 

Выводы

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

  • В целом, Chrome является самым быстрым, разгоняя 1025 операций в секунду за 27,0. В 10 раз быстрее, чем с помощью Array.join()

  • Firefox находится на втором месте со скоростью 550 операций в секунду (но 20,0, похоже, регрессировал). Array.join примерно в 4-5 раз медленнее.

  • IE является самым быстрым с прямой конкатенацией строк, он очень медленный, используя Array.join и Array.push. IE 9 делает Array.join не таким медленным, и все абстракции SB работают почти одинаково (вероятно, из-за перегрузки метода)

  • Опера - единственный, где Array.join действительно помогает, это в 2-3 раза быстрее, чем конкатенация строк.

  • Создание StringBuilder для абстрагирования от проблем производительности каждого браузера приносит больше вреда, чем пользы. Затраты на вызовы методов могут быть приемлемыми, но, как представляется, существует тенденция, что браузеры более умно обрабатывают конкатенацию строк. Это имеет смысл только в том случае, если вашей целевой аудиторией является Opera, поэтому вы можете использовать Array.join там и использовать конкатенацию строк везде (это означает, что все другие браузеры получают удар)

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

Другой тестовый кейс

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

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

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

Ответ 2

из nofollow noreferrer" > :

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

Ответ 3

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

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

В JavaScript нет StringBuilder.

Ответ 4

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

Пример:

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

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

Ответ 5

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

Ответ 6

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

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

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

Думаю, вам нужно будет сделать свой собственный бенчмаркинг, и результаты могут отличаться и между браузерами. Однако, даже если он не улучшает производительность, он может по-прежнему считаться "полезным" для программистов, которые используются для кодирования с помощью StringBuilders на таких языках, как С# или Java.

Ответ 7

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

Здесь однозначно, кроме как из надежной книги:

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

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

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

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

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

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

Ответ 8

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

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

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

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

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

var immutableString = "Hello";

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

immutableString = immutableString + "World";

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

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

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

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

Ответ 9

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

Ответ 10

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