Diffusion en chaîne en JavaScript

184

J'ai trouvé trois façons de convertir une variable Stringen JavaScript.
J'ai recherché ces trois options dans le code source de jQuery, et elles sont toutes utilisées .
J'aimerais savoir s'il y a des différences entre eux:

value.toString()
String(value)
value + ""

DEMO

Ils produisent tous le même résultat, mais l'un d'eux est-il meilleur que les autres?
Je dirais que le + ""a l'avantage de sauver certains personnages, mais ce n'est pas ce gros avantage, autre chose?

gdoron soutient Monica
la source
1
Il me semble que si toutes choses sont égales par ailleurs, la norme toString()serait la voie à suivre.
asawyer
1
@asawyer. Et pourquoi est-ce que? S'ils produisent tous le même résultat et font de même, choisissez-en un et allez-y. C'est mon avis si c'est vraiment le cas ici .
gdoron soutient Monica le
1
Les deux premières méthodes doivent être équivalentes (vous devez vérifier le standard mais le constructeur appellera toString). Le 3ème produit HABITUELLEMENT le même résultat mais il implique un mécanisme très différent (outre la vitesse, il implique des appels différents donc ce n'est peut-être pas ce que vous attendez pour chaque type d'objet).
Adriano Repetti
6
À mon avis, toStringc'est sémantiquement le moyen le plus clair d'auto-documenter le fait que vous essayez d'obtenir une chaîne équivalente à un objet. String(...)est un peu obtus, et value + ""c'est un peu un hack. Cela vous donne également la possibilité de remplacer la valeur toStringpar défaut avec une implémentation personnalisée si jamais vous en aviez besoin, je suppose, comme avantage secondaire mineur.
asawyer
2
@Adriano. Mais + ""c'est le plus rapide selon le jsperf, donc ... il le fait d'une autre manière je suppose.
gdoron soutient Monica le

Réponses:

213

Ils se comportent différemment quand ils le valuesont null.

  • null.toString()renvoie une erreur - Impossible d'appeler la méthode 'toString' de null
  • String(null)renvoie - "null"
  • null + ""renvoie également - "null"

Un comportement très similaire se produit si valuec'est undefined(voir la réponse de jbabey ).

En dehors de cela, il existe une différence de performance négligeable qui, à moins que vous ne les utilisiez dans d'énormes boucles, ne vaut pas la peine de s'inquiéter.

Connell
la source
C'est en fait une différence intéressante. Vous devez donc vous abstenir d'utiliser toString()lorsque vous n'avez pas encore vérifié null.
Sammy S.
@SammyS. Je ne sais pas si l'impression nullou undefinedà l'écran est un comportement plus souhaitable qu'une erreur javascript ...
Justus Romijn
@ JustusRomijn: C'est vrai. En attendant, j'ai commencé à utiliser le type Option pour gérer ces erreurs.
Sammy S.
vous pouvez vérifier n'importe laquelle de ces variables transtypées avec typeof pour vérifier la chaîne. typeof (null + '') == 'string'
Bruce Lim
4
Il y a un autre cas où ils se comportent différemment. v + ''renvoie un résultat incorrect si v a à la fois les méthodes toString () et valueOf (). La concaténation ignorera toString () et utilisera valueOf (). Exemple de classe pour laquelle la concaténation échoue: github.com/processing-js/processing-js/blob/…
Mikita Belahlazau
26

Il existe des différences, mais elles ne sont probablement pas pertinentes pour votre question. Par exemple, le prototype toString n'existe pas sur des variables non définies, mais vous pouvez convertir undefined en chaîne à l'aide des deux autres méthodes:

var foo;

var myString1 = String(foo); // "undefined" as a string

var myString2 = foo + ''; // "undefined" as a string

var myString3 = foo.toString(); // throws an exception

http://jsfiddle.net/f8YwA/

jbabey
la source
3
Si une variable n'est pas du tout définie, vous obtiendrez toujours une erreur pour String(). Exemple: String(test);lance Uncaught ReferenceError: test is not defined, tandis que var test; String(test);cela entraînera "undefined".
Anthony
17

Ils se comportent de la même manière mais toStringfournissent également un moyen de convertir un nombre de chaînes binaires, octales ou hexadécimales:

Exemple:

var a = (50274).toString(16)  // "c462"
var b = (76).toString(8)      // "114"
var c = (7623).toString(36)   // "5vr"
var d = (100).toString(2)     // "1100100"
Sarfraz
la source
9

Selon ce test JSPerf , ils diffèrent en vitesse. Mais à moins que vous ne les utilisiez en grande quantité, n'importe lequel d'entre eux devrait fonctionner correctement.

Par souci d' exhaustivité: comme un avocat l'a déjà mentionné, vous pouvez également utiliser la .toString()méthode.

Sammy S.
la source
2
Ce jsperf a le même test deux fois, je l'ai édité Et le new String()retourne un objet pas unString
gdoron supporte Monica
new String()renvoie un objet oui. String(), cependant, renvoie une chaîne, qui est celle de la question.
Connell
2
Ce n'est pas entièrement vrai. Comme vous pouvez le voir dans les résultats, la concaténation d'une chaîne vide et d'un objet ne donne pas le même résultat que la concaténation d'un objet et d'une chaîne vide. De plus, new String(blarg)vous donne un Stringobjet sur lequel vous pouvez faire appel toString(). Dans mon débogueur Chrome, ils résultent effectivement du même type d'objet, à l'exception de cette différence.
Sammy S.
@SammyS. Pourriez-vous s'il vous plaît ajouter des exemples de résultats de performance à votre réponse? Le lien jsperf est actuellement en panne et le sera certainement au cours des 5 prochaines années.
mxmlnkn
9

En plus de tout ce qui précède, il faut noter que, pour une valeur définie v:

  • String(v) appels v.toString()
  • '' + vappels v.valueOf()avant tout autre type de diffusion

Nous pourrions donc faire quelque chose comme:

var mixin = {
  valueOf:  function () { return false },
  toString: function () { return 'true' }
};
mixin === false;  // false
mixin == false;    // true
'' + mixin;       // "false"
String(mixin)     // "true"

Testé dans FF 34.0 et Node 0.10

Simone C.
la source
8

si vous êtes d'accord avec null, undefined, NaN, 0 et false, tout cast en «» (s ? s+'' : '')est alors plus rapide.

voir http://jsperf.com/cast-to-string/8

Remarque - il existe actuellement des différences significatives entre les navigateurs.

jldec
la source
4

Exemple concret: J'ai une fonction de journal qui peut être appelé avec un nombre arbitraire de paramètres: log("foo is {} and bar is {}", param1, param2). Si un DEBUGindicateur est défini sur true, les crochets sont remplacés par les paramètres donnés et la chaîne est passée à console.log(msg). Les paramètres peuvent être et seront des chaînes, des nombres et tout ce qui peut être retourné par les appels JSON / AJAX, peut-être même null.

  • arguments[i].toString()n'est pas une option, à cause des nullvaleurs possibles (voir la réponse de Connell Watkins)
  • JSLint se plaindra arguments[i] + "". Cela peut ou non influencer une décision sur ce qu'il faut utiliser. Certaines personnes adhèrent strictement à JSLint.
  • Dans certains navigateurs, concaténer des chaînes vides est un peu plus rapide que d'utiliser une fonction de chaîne ou un constructeur de chaîne (voir le test JSPerf dans la réponse Sammys S.). Dans Opera 12 et Firefox 19, la concaténation de chaînes vides est ridiculement plus rapide (95% dans Firefox 19) - ou du moins JSPerf le dit.
Jack
la source
1

Sur cette page, vous pouvez tester vous-même les performances de chaque méthode :)

http://jsperf.com/cast-to-string/2

ici, sur toutes les machines et tous les navigateurs, ' "" + str ' est le plus rapide, (String) str est le plus lent

itinance
la source