Conversiones/casteos y coerciones de tipos en javascript por StringManolo

Iniciado por @XSStringManolo, 24 Abril 2020, 10:09 AM

0 Miembros y 1 Visitante están viendo este tema.

@XSStringManolo

En javascript tenemos conversores léxicos en forma de métodos y funciones; Number(), parseInt(), parseFloat(), String(), Boolean(), Object(), toString()... y también disponemos de otros métodos que hacen conversiones indirectas o que directamente retornan otro tipo de dato como .join() y .split(). Incluso se hacen casteos y conversiones de forma transparente. Por ejemplo en el conjunto de sentencias var nombre = "Manolo"; var inicial = nombre.charAt(0); "Manolo" es un literal de un tipo de data primitivo. No tiene métodos aplicables. El motor de javascript crea un nuevo objeto temporal al que pasa una referencia de nombre como parámetro. A este nuevo objeto String se le puede aplicar el método charAt(). Tras ello se retorna el valor como expresión (en este caso se asigna a la variable inicial). Y se asigna null a la variable temporal utilizada. A esta técnica se la conoce como AutoBoxing. Sin embargo lo que quiero comentar no es nada de esto si no los operadores que realizan casteos implícitos.

Sin duda el que más se utiliza de ellos de forma no premeditada es el operador ==. Cuando se comparan dos valores de tipos distintos el operador == hace una conversión automática/implícita de tipo (coerción de tipos) en el caso que sea necesaria. Por ese motivo en muchos casos debemos utilizar en su lugar el operador ===. Pasa lo mismo con otros operadores de comparación como puedan ser el != < >= ...

Por otro lado el operador de casteo implícito más utilizado para coerción es el "". Se abusa de que ante la comparación de un string literal y otro tipo de dato prevalece la concatencación del string sobre una operación de adición.
n = 1; m = 2;
doce = n + "" + m;
También puedes usar un array vacio. alert(1 + [] + 2);

Uno menos conocido es el operador unario +.
La variable doce contiene ahora mismo el string literal de tipo primitivo "12". Si queremos convertirlo a número utilizamos el más. doce = +doce;

Podemos comprobarlo de la siguiente manera.
Código (javascript) [Seleccionar]
var doce = "" + 12;
alert(typeof(doce)); /* String */

doce = +doce;
alert(typeof(doce)); /* Number */


Otra forma de convertir a número es utilizando doce-0 o ~~doce.
Código (javascript) [Seleccionar]
var doce = "" + 12;
alert(typeof(doce)); /* String */

doce = doce-0;
alert(typeof(doce)); /* Number */


IMPORTANTE: Este tipo de casteo con operador unario + tiene resultados equivalente a utilizar Number() y no a parseInt();
Tienen pequeñas diferencias. Por ejemplo si casteas un string vacio utilizando parseInt() obtendrás un NaN (Not a Number, No es un número). Por el contrario si usas Number() o el casteo implícito con los operadores el string vacio se castea a 0. Con el doble bitwise ~~ puedes hacer interger overflow o que te retorne 0 con números grandes asique hay que tenerlo en cuenta. Por otro lado tiene la característica de castear a 0 valores como undefined o números con strings. Hay más operadores de bits que actual igual que el doble bitwise a la hora de castear.

También es recomendado utilizar mètodos/funciones cuando el código no queda claro o añadir comentarios al código.

Otro operador implícito es el ! o !! que puede utilizarse para castear valores falsos o verdaderos a sus contrapuestos o respectivos homólogos booleanos.

Precaución a la hora de hacer casteos a booleanos usando objetos. Por ejemplo en el código:
Código (javascript) [Seleccionar]
booleano = new Boolean(0);
if (booleano) alert("Hola");
La condición se cumple ejecutando el alert debido a que exite un objeto. Lo que se debe hacer es usar Boolean(0) sin el new para que se haga el Autoboxing y obtener el valor booleano primitivo (y no un objeto referenciado Boolean con valor false que se evalua como true por existir el objeto). El operador !! también es una forma válida de no crear el objeto y obtener un booleano primitivo.

Otras conversiones incluyen operaciones con strings. Si bien el + concatena un número y un string, el resto de operadores unarios no siguen la misma norma.
var dos = "6" - "2" * "2";

[u]nsigned

Genial aporte, JS es tan grande y complejo que uno nunca deja de aprender cosas nuevas sobre el, ya sea corriendo en browser o en node. Este tipo de detalles es lo que llevo a crear TypeScript, aunque a mi la verdad no me gusta para nada usar un 'lenguaje' (ya se que es solo un superset) tan verboso. Prefiero usar JS porque te obliga a tener cierto dominio y aplicar buenas practicas si no queres que tu codigo sea un infierno a medida que tu aplicaciones emieza a escalar....


No hay atajo ante la duda, el misterio se hace aquí...
Se hace carne en cada uno, el misterio es existir!

@XSStringManolo

Muchas gracias. Coincido con lo que dices. Yo me animaría mas a probar un set más pequeño que un superset. Ya tiene bastante chicha js de por sí, aunque typescript parece que añade cosas bastante útiles para quien venga de otros lenguajes.


Una de las cosas que peor llevo es distribuir bien los programas. Suelo acabar mezclando todo a pesar de hacer mucha función pura o encapsular la funcionalidad. Creo que el lenguaje invita bastante a atajar en lugar de escribir más código para que quede todo más isolado.