¿Cuál es la mejor manera de convertir un número en una cadena en JavaScript?

519

¿Cuál es la "mejor" forma de convertir un número en una cadena (en términos de ventaja de velocidad, ventaja de claridad, ventaja de memoria, etc.)?

Algunos ejemplos:

  1. String(n)

  2. n.toString()

  3. ""+n

  4. n+""

Pacerier
fuente

Respuestas:

516

Me gusta esto:

var foo = 45;
var bar = '' + foo;

En realidad, aunque normalmente lo hago así por simple conveniencia, más de 1,000 de iteraciones parece que para la velocidad bruta hay una ventaja para.toString()

Vea las pruebas de rendimiento aquí (no por mí, pero las encontré cuando fui a escribir las mías): http://jsben.ch/#/ghQYR

El más rápido basado en la prueba JSPerf anterior: str = num.toString();

Cabe señalar que la diferencia de velocidad no es demasiado significativa si considera que puede realizar la conversión de cualquier manera 1 millón de veces en 0.1 segundos .

Actualización: la velocidad parece diferir mucho según el navegador. En Chrome num + ''parece ser el más rápido basado en esta prueba http://jsben.ch/#/ghQYR

Actualización 2: De nuevo, según mi prueba anterior, se debe tener en cuenta que Firefox 20.0.1 ejecuta .toString()aproximadamente 100 veces más lento que la '' + nummuestra.

scunliffe
fuente
58
Hay casos en los que la conversión puede no devolver una respuesta preferible: '' + 123e-50devoluciones "1.23e-48".
hongymagic
21
@hongymagic: esa respuesta es, de hecho, la única concebible: al número no le importa ni sabe cómo se ingresó, y la representación impresa estándar es exactamente con un dígito antes del punto.
Svante
44
Ejecuté la prueba en jsben.ch/ghQYR , ¡cada vez que me muestra un resultado diferente!
Maryam Saeidi
2
Me gusta esta respuesta porque a null foono arroja un error.
ttugates
2
@MaryamSaeidi: Usando Drublic 's jsperf.com prueba anterior parece más consistente.
Giraldi
364

En mi opinión, n.toString()toma el premio por su claridad, y no creo que tenga ningún gasto adicional.

CarlosZ
fuente
Lleva algunos gastos generales a pesar de que es insignificante en las versiones recientes del navegador. Al menos en Firefox Quantum
peterchaula
11
Esto no es seguro. n puede ser nulo o indefinido.
david.pfx
20
@ david.pfx la pregunta pregunta cómo convertir valores numéricos en una cadena. Proporcionar ejemplos de valores no numéricos (por ejemplo null, undefined) que no funcionan con esta respuesta difícilmente lo hace "inseguro".
Michael Martin-Smucker
55
@ MichaelMartin-Smucker: Si escribes mucho JS te das cuenta de que las cosas rara vez se cortan y secan. La pregunta estaba abierta y la OMI, una buena respuesta debería al menos reconocer el problema de una cadena que en realidad es nula o indefinida. YMMV.
david.pfx
@ david.pfx He escrito MUCHOS js y no recuerdo la última vez que necesité un número como cadena y cualquier cosa que no fuera un número como cadena hubiera sido suficiente. Esta es la respuesta correcta. No hay respuesta para el manejo nullo, undefinedya que es específico de la aplicación, aunque imagino que (n || defaultNumber).toString() es lo que la mayoría de la gente querría en tal situación, estoy totalmente en desacuerdo con que deberíamos trabajarlo en todas las preguntas. Se trataba de convertir números a cadenas, buena arquitectura y otras conversiones de tipo donde sea necesario, son lecciones separadas.
George Reith
73

Las conversiones explícitas son muy claras para alguien que es nuevo en el lenguaje. El uso de la coerción de tipo, como han sugerido otros, conduce a la ambigüedad si un desarrollador no conoce las reglas de coerción. En última instancia, el tiempo de desarrollador es más costoso que el tiempo de CPU, por lo que optimizaría para el primero a costa de este último. Dicho esto, en este caso la diferencia probablemente sea insignificante, pero si no, estoy seguro de que hay algunos compresores JavaScript decentes que optimizarán este tipo de cosas.

Entonces, por las razones anteriores, iría con: n.toString()o String(n). String(n)es probablemente una mejor opción porque no fallará si nes nulo o no está definido.

Bryan Kyle
fuente
12
La pregunta era sobre convertir números, no sobre convertir números, o null, o undefined. Si nes nullo se undefineddebe a un error en mi programa, prefiero que mi programa falle en este estado, para tener una mejor oportunidad de encontrar y corregir el error. Los bloqueos del programa son regalos para el programador, para ayudarla a encontrar los errores :-). La alternativa es entregar un software que no funciona como se diseñó, habiendo pasado por alto los errores. Por lo tanto, no soy fanático de usar String(n)para enmascarar un error.
Matt Wallis
1
String(n)es bueno para usar en un estilo funcional, por ejemplo, con la combinación de subrayado _.compose(funcThatNeedsAStringParam, String).
Rik Martins
2
La cadena (nulo) no bloqueará el programa, pero devolverá la cadena literal "nulo", que probablemente no sea lo que desea. Si los datos pueden ser legítimamente nulos, entonces debe manejarlos explícitamente.
Peter Smartt
1
@MattWallis Creo que esa debería ser la decisión del desarrollador, no del respondedor, ¿no le parece?
forresthopkinsa
31

... El analizador de JavaScript intenta analizar la notación de punto en un número como un literal de coma flotante.

2..toString(); // the second point is correctly recognized
2 .toString(); // note the space left to the dot
(2).toString(); // 2 is evaluated first

Fuente

Mohammad Arif
fuente
17

Lengua en la mejilla, obviamente:

var harshNum = 108;
"".split.call(harshNum,"").join("");

O en ES6 simplemente podría usar cadenas de plantilla :

var harshNum = 108;
`${harshNum}`;
cssimsek
fuente
Si ejecuto los puntos de referencia con plantillas ES6, a veces incluso resulta ser más rápido que el '' + numbermétodo. Dicho esto, los resultados de estos puntos de referencia varían mucho cuando se realizan varias veces, por lo que no estoy seguro de si deben tomarse demasiado en serio.
Nico Van Belle
15

Otras respuestas ya cubrieron otras opciones, pero prefiero esta:

s = `${n}`

Breve, sucinto, ya utilizado en muchos otros lugares (si está utilizando una versión moderna de framework / ES), por lo que es una apuesta segura que cualquier programador lo entenderá.

No es que (generalmente) importe mucho, pero también parece estar entre los más rápidos en comparación con otros métodos .

johndodo
fuente
También es seguro si n podría no ser un número.
david.pfx
Pero n.toString()entonces, ¿no es así?
amn
1
@amn si nes undefined, arrojará un error de sintaxis al usar.toString()
Jee Mok
¿No da esto el mismo resultado que String(n)en todos los casos? La única diferencia es que está menos claro.
Bennett McElwee
Y mucho más lento.
Adrian Bartholomew
12

La forma más sencilla de convertir cualquier variable en una cadena es agregar una cadena vacía a esa variable.

5.41 + ''    // Result: the string '5.41'
Math.PI + '' // Result: the string '3.141592653589793'
Sgokhales
fuente
2
Tenga en cuenta que debe estar dentro de parens: (5.41 + '')para usar los métodos de cadena como .substring()y otros
Gjaa
¿Por qué es necesario tener eso en cuenta?
Adrian Bartholomew
7

Si necesita formatear el resultado a un número específico de lugares decimales, por ejemplo, para representar la moneda, necesita algo como el toFixed()método.

number.toFixed( [digits] )

digits es el número de dígitos que se mostrarán después del decimal.

Tim
fuente
2
Inseguro a menos que sepa que es un número.
david.pfx
6

Usé https://jsperf.com para crear un caso de prueba para los siguientes casos:

number + ''
`${number}`
String(number)
number.toString()

https://jsperf.com/number-string-conversion-speed-comparison

A partir del 24 de julio de 2018, los resultados dicen que number + ''es el más rápido en Chrome, en Firefox que se vincula con los literales de cadena de plantilla.

Ambos String(number), y number.toString()son alrededor de un 95% más lentos que la opción más rápida.

pruebas de rendimiento, descripción anterior

Erick
fuente
2

Me gustan los dos primeros ya que son más fáciles de leer. Tiendo a usar, String(n)pero es solo una cuestión de estilo que cualquier otra cosa.

Eso es a menos que tenga una línea como

var n = 5;
console.log ("the number is: " + n);

lo cual es muy explicativo

Aleadam
fuente
2

Creo que depende de la situación, pero de todos modos puede usar el .toString()método, ya que es muy claro de entender.

Serghei
fuente
2

.toString () es la función de conversión integrada, no soy un experto en esos detalles, pero cada vez que comparamos metodologías explícitas de versos de conversión de tipo incorporado, siempre se prefieren soluciones integradas.

Mubeen Khan
fuente
1

Si tuviera que tener todo en cuenta, sugeriré seguir

var myint = 1;
var mystring = myint + '';
/*or int to string*/
myint = myint + ''

En mi humilde opinión, es la forma más rápida de convertir a cadena. Corrígeme si estoy equivocado.

Kumar
fuente
1

La única solución válida para casi todos los posibles casos existentes y futuros (entrada es número, nulo, indefinido, símbolo, cualquier otra cosa) es String(x). No utilice 3 formas de operación simple, basándose en suposiciones de tipo de valor, como "aquí convierto definitivamente el número a cadena y aquí definitivamente booleano a cadena".

Explicación:

String(x)maneja nulos, indefinidos, símbolos, [cualquier cosa] y pide .toString()objetos.

'' + xinvoca .valueOf()x (conversión a número), arroja símbolos, puede proporcionar resultados dependientes de la implementación.

x.toString() tira nulos e indefinidos.

Nota: String(x)aún fallará en objetos sin prototipos comoObject.create(null) .

Si no le gustan las cadenas como 'Hola, indefinido' o desea admitir objetos sin prototipos, use la siguiente función de conversión de tipos:

/**
 * Safely casts any value to string. Null and undefined are converted to ''.
 * @param  {*} value
 * @return {string}
 */
function string (str) {
  return value == null ? '' : (typeof value === 'object' && !value.toString ? '[object]' : String(value));
}
Alexander Shostak
fuente
1

Con literales numéricos, el punto para acceder a una propiedad debe distinguirse del punto decimal. Esto le deja con las siguientes opciones si desea invocar a String () en el número literal 123:

123..toString()
123 .toString() // space before the dot 123.0.toString()
(123).toString()
Mohit Dabas
fuente
1

Los siguientes son los métodos para convertir un entero en una cadena en JS

Los métodos se organizan en orden decreciente de rendimiento.

(Los resultados de la prueba de rendimiento son dados por @DarckBlezzer en su respuesta)

var num = 1

Método 1:

num = `$ {num}`

Método 2:

num = num + ''

Método 3:

num = cadena (num)

Método 4:

num = num.toString ()

Nota: no puede llamar directamente a tostring () desde un número

Por ejemplo: 2.toString () arrojará Error de sintaxis no capturado : token no válido o inesperado

Arun Joshla
fuente
0

Si tiene curiosidad sobre cuál es el más eficaz, consulte esto donde comparo todas las diferentes conversiones de Número -> Cadena.

Parece 2+''o 2+""son los más rápidos.

https://jsperf.com/int-2-string

Alex Cory
fuente
0

También podemos usar el constructor de cadenas . Según este punto de referencia , es la forma más rápida de convertir un Número a Cadena en Firefox 58, aunque es más lento que " + numen el popular navegador Google Chrome.

Peterchaula
fuente
0

El método toFixed()también resolverá el propósito.

var n = 8.434332;
n.toFixed(2)  // 8.43
Shaik Rasool
fuente
0

Puede llamar a Numberobjeto y luego llamar toString().

Number.call(null, n).toString()

Puedes usar este truco para otros objetos nativos de JavaScript.

ufadiz
fuente
0

Acabo de encontrar esto recientemente, los métodos 3 y 4 no son apropiados porque cómo se copian las cadenas y luego se juntan. Para un programa pequeño, este problema es insignificante, pero para cualquier aplicación web real, esta acción en la que tenemos que lidiar con manipulaciones de cadenas de frecuencia puede afectar el rendimiento y la legibilidad.

Aquí está el enlace de la lectura .

Roger
fuente
0

Voy a volver a editar esto con más datos cuando tenga tiempo para hacerlo, por ahora está bien ...

Prueba en nodejs v8.11.2: 2018/06/06

let i=0;
    console.time("test1")
    for(;i<10000000;i=i+1){
    	const string = "" + 1234;
    }
    console.timeEnd("test1")
    
    i=0;
    console.time("test1.1")
    for(;i<10000000;i=i+1){
    	const string = '' + 1234;
    }
    console.timeEnd("test1.1")
    
    i=0;
    console.time("test1.2")
    for(;i<10000000;i=i+1){
    	const string = `` + 1234;
    }
    console.timeEnd("test1.2")
    
    i=0;
    console.time("test1.3")
    for(;i<10000000;i=i+1){
    	const string = 1234 +  '';
    }
    console.timeEnd("test1.3")
    
    
    i=0;
    console.time("test2")
    for(;i<10000000;i=i+1){
    	const string = (1234).toString();
    }
    console.timeEnd("test2")
    
    
    i=0;
    console.time("test3")
    for(;i<10000000;i=i+1){
    	const string = String(1234);
    }
    console.timeEnd("test3")
    
    
    i=0;
    console.time("test4")
    for(;i<10000000;i=i+1){
    	const string = `${1234}`;
    }
    console.timeEnd("test4")
    
    i=0;
    console.time("test5")
    for(;i<10000000;i=i+1){
    	const string = 1234..toString();
    }
    console.timeEnd("test5")
    
    i=0;
    console.time("test6")
    for(;i<10000000;i=i+1){
    	const string = 1234 .toString();
    }
    console.timeEnd("test6")

salida

test1: 72.268ms
test1.1: 61.086ms
test1.2: 66.854ms
test1.3: 63.698ms
test2: 207.912ms
test3: 81.987ms
test4: 59.752ms
test5: 213.136ms
test6: 204.869ms
DarckBlezzer
fuente
Yay - ¡test4 es lo que uso regularmente!
Adrian Bartholomew
0

Parece resultados similares cuando se usa node.js. Ejecuté este script:

let bar;
let foo = ["45","foo"];

console.time('string concat testing');
for (let i = 0; i < 10000000; i++) {
    bar = "" + foo;
}
console.timeEnd('string concat testing');


console.time("string obj testing");
for (let i = 0; i < 10000000; i++) {
    bar = String(foo);
}
console.timeEnd("string obj testing");

console.time("string both");
for (let i = 0; i < 10000000; i++) {
    bar = "" + foo + "";
}
console.timeEnd("string both");

y obtuve los siguientes resultados:

 node testing.js
string concat testing: 2802.542ms
string obj testing: 3374.530ms
string both: 2660.023ms

Veces similares cada vez que lo ejecuté.

Shahaed
fuente