273 votes

Les chaînes de caractères JavaScript sont-elles immuables ? Ai-je besoin d'un "constructeur de chaîne de caractères" en JavaScript ?

Est-ce que JavaScript utilise des chaînes de caractères immuables ou mutables ? Ai-je besoin d'un "string builder" ?

4 votes

Oui, ils sont immuables et vous avez besoin d'un "string builder" de quelque sorte. Lisez ce blog.codeeffects.com/Article/String-Builder-In-Java-Script ou celui-ci codeproject.com/KB/scripting/stringbuilder.aspx

3 votes

Intéressant, ces exemples contredisent mes conclusions dans ma réponse.

330voto

Juan Mendes Points 31678

Ils sont immuables. Vous ne pouvez pas modifier un caractère dans une chaîne avec quelque chose comme var myString = "abbdef"; myString[2] = 'c' . Les méthodes de manipulation de chaînes de caractères telles que trim , slice renvoient de nouvelles chaînes.

De la même manière, si vous avez deux références à la même chaîne de caractères, la modification de l'une n'affecte pas l'autre

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

Cependant, j'ai toujours entendu ce qu'Ash a mentionné dans sa réponse (que l'utilisation de Array.join est plus rapide pour la concaténation), j'ai donc voulu tester les différentes méthodes de concaténation de chaînes et abstraire la façon la plus rapide dans un StringBuilder. J'ai écrit quelques tests pour voir si c'était vrai (ça ne l'est pas !).

C'est ce que je pensais être la méthode la plus rapide, même si je n'arrêtais pas de penser que l'ajout d'un appel de méthode pourrait ralentir le processus...

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('');
}

Voici des tests de vitesse de performance. Tous les trois créent une gigantesque chaîne de caractères composée de la concaténation de "Hello diggity dog" cent mille fois dans une chaîne vide.

J'ai créé trois types de tests

  • Utilisation Array.push y Array.join
  • Utiliser l'indexation des tableaux pour éviter Array.push puis en utilisant Array.join
  • Concaténation directe de chaînes de caractères

J'ai ensuite créé les trois mêmes tests en les abstrayant en StringBuilderConcat , StringBuilderArrayPush y StringBuilderArrayIndex http://jsperf.com/string-concat-without-sringbuilder/5 Allez-y et faites des tests pour que nous puissions obtenir un bon échantillon. Notez que j'ai corrigé un petit bug, donc les données pour les tests ont été effacées, je mettrai à jour le tableau une fois qu'il y aura assez de données de performance. Aller à http://jsperf.com/string-concat-without-sringbuilder/5 pour l'ancien tableau de données.

Voici quelques chiffres (dernière mise à jour en mars 2018), si vous ne souhaitez pas suivre le lien. Le nombre sur chaque test est en 1000 opérations/seconde ( plus c'est haut, mieux c'est )

Navigateur

Index

Pousser

Concat

SBIndex

SBPush

SBConcat

Chrome 71.0.3578

988

1006

2902

963

1008

2902

Firefox 65

1979

1902

2197

1917

1873

1953

Bord

593

373

952

361

415

444

Exploder 11

655

532

761

537

567

387

Opera 58.0.3135

1135

1200

4357

1137

1188

4294

Résultats

  • Aujourd'hui, tous les navigateurs modernes gèrent bien la concaténation de chaînes de caractères. Array.join ne fonctionne qu'avec IE 11

  • Dans l'ensemble, Opera est le plus rapide, 4 fois plus rapide que Array.join.

  • Firefox est deuxième et Array.join est à peine plus lent dans FF mais considérablement plus lent (3x) dans Chrome.

  • Chrome est troisième mais string concat est 3 fois plus rapide que Array.join

  • La création d'un StringBuilder ne semble pas trop affecter les performances.

J'espère que quelqu'un d'autre trouvera cela utile

Cas de test différent

Puisque @RoyTinker pensait que mon test était défectueux, j'ai créé un nouveau cas qui ne crée pas une grosse chaîne en concaténant la même chaîne, mais qui utilise un caractère différent à chaque itération. La concaténation de chaînes de caractères semble toujours plus rapide ou tout aussi rapide. Lançons ces tests.

Je suggère que tout le monde continue à réfléchir à d'autres façons de tester cela, et n'hésitez pas à ajouter de nouveaux liens vers différents cas de test ci-dessous.

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

0 votes

@Juan, le lien que vous nous avez demandé de visiter concatène une chaîne de 112 caractères 30 fois. Voici un autre test qui pourrait aider à équilibrer les choses - Array.join vs concaténation de chaînes sur 20 000 chaînes de 1 caractère différentes (join est beaucoup plus rapide sur IE/FF). jsperf.com/join-vs-str-concat-large-array

1 votes

@RoyTinker Roy, oh Roy, vos tests trichent parce que vous créez le tableau dans la configuration du test. Voici le vrai test en utilisant des caractères différents jsperf.com/string-concat-without-sringbuilder/7 N'hésitez pas à créer de nouveaux cas de test, mais la création du tableau fait partie du test lui-même

0 votes

@JuanMendes Mon objectif était de restreindre le cas de test à une comparaison stricte de join par rapport à la concaténation de chaînes, d'où la construction du tableau avant le test. Je ne pense pas que ce soit tricher si cet objectif est compris (et join énumère le tableau en interne, donc ce n'est pas tricher d'omettre une boucle for du test join).

44voto

minty Points 7864

Du livre rhino:

En JavaScript, les chaînes de caractères sont des objets immuables, ce qui signifie que les caractères à l'intérieur d'elles ne peuvent pas être modifiés et que toutes les opérations sur les chaînes créent en réalité de nouvelles chaînes. Les chaînes sont assignées par référence, et non par valeur. En général, lorsqu'un objet est assigné par référence, un changement effectué sur l'objet par le biais d'une référence sera visible à travers toutes les autres références à l'objet. Cependant, comme les chaînes de caractères ne peuvent pas être modifiées, vous pouvez avoir plusieurs références à un objet chaîne et ne pas vous inquiéter que la valeur de la chaîne change sans que vous le sachiez.

7 votes

Lien vers une section appropriée du livre sur les rhinocéros : books.google.com/…

132 votes

Le devis du livre Rhino (et donc cette réponse) est incorrect ici. En JavaScript, les chaînes de caractères sont des types de valeur primitive et non des objets (spécification). En fait, à partir de ES5, ils sont l'un des seuls 5 types de valeurs aux côtés de null undefined number et boolean. Les chaînes sont assignées par valeur et non par référence et sont transmises en tant que telles. Ainsi, les chaînes ne sont pas seulement immuables, elles sont une valeur. Changer la chaîne "hello" pour "world" revient à décider qu'à partir de maintenant, le numéro 3 est le numéro 4... cela n'a aucun sens.

2 votes

@BenjaminGruenbaum Donc, pourrait-on dire que les chaînes JS sont immuables, mais c'est parce que ce sont des primitives au lieu d'objets?

23voto

Ash Points 31541

Astuce de performance :

Si vous devez concaténer de grandes chaînes, mettez les parties de la chaîne dans un tableau et utilisez la méthode Array.Join() pour obtenir la chaîne globale. Cela peut être beaucoup plus rapide pour concaténer un grand nombre de chaînes.

Il n'y a pas de StringBuilder en JavaScript.

0 votes

Je sais qu'il n'y a pas de stringBuilder, msAjax en a un, et je me demandais simplement si c'est utile

6 votes

Qu'est-ce que cela a à voir avec le fait que les chaînes de caractères soient immuables ou non ?

4 votes

@docgnome: Parce que les chaînes de caractères sont immuables, la concaténation de chaînes de caractères nécessite la création de plus d'objets que l'approche Array.join

0voto

JC Grubbs Points 7833

Les chaînes de caractères en JavaScript sont en effet immuables.

0 votes

Lien vers la doc ? Je ne trouve pas de détails à ce sujet.

1 votes

"tenter de définir un caractère individuel ne fonctionnera pas" -- developer.mozilla.org/fr/JavaScript/Reference/Global_Objects‌​/…

-1voto

Glenn Slaven Points 15742

Les chaînes de caractères en JavaScript sont immuables

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X