Wextensible

Un sitio personal para aprender desarrollo web

Vista de los primeros bytes de un archivo PNG

Si queremos estudiar como se conforman los bytes en un archivo, por ejemplo un PNG de imagen, necesitaremos una herramienta para observar el contenido. Con este visor binario podemos cargar un archivo del ordenador y ver sus bytes con varias vistas como binaria, hexadecimal y decimal. Por ejemplo en la Figura se observan los hexadecimales de los primeros bytes de un archivo PNG.

El redondeo estándar para cálculos en una factura

El redondeo estándar de fracciones 0.5 se basa en observar el siguiente dígito después de los especificados para redondeo y si es igual o mayor que 5 redondeará arriba, en otro caso se quedará como está. Esta regla se usa en aplicaciones contables y comerciales donde entran en juego cálculos con importes de moneda. Es el caso del cálculo de una factura, realizando un ejemplo para ver cómo redondeamos los resultados parciales y totales.

Los métodos como toFixed() podrían redondear a un número determinado de dígitos fraccionarios. Pero no ejecutan el redondeo estándar en algunos casos. Por ejemplo, si lo aplicamos a 1.025 redondeando a dos dígitos resultará 1.02 en lugar del esperado 1.03. Así que el tema se dedica a presentar ese problema y buscar una función que ejecute correctamente el redondeo estándar.

El formato IEEE754 redondea el número cuando hay un exceso de bits

Entender el redondeo que aplica el formato IEEE754 es imprescindible para saber por qué suceden algunas cosas con los números en JavaScript. Por ejemplo, por qué la operación 1.33 × 1.4 = 1.862 nos da el resultado 1.8619999999999999 en JavaScript, por debajo del valor esperado. Mientras que 1.33 × 1.1 = 1.463 resulta 1.4630000000000003, por encima del valor.

Generador de formato local del método toLocaleString()

Dedicaremos este tema a ver métodos que aplican especialmente a números reales, mejor dicho, a números decimales con parte fraccionaria. Uno de ellos es parseFloat() que convierte un string en un number. El método toExponential() nos permitirán poner un número en formato exponencial mientras que toFixed() y toPrecision() sirven para ajustar el número de dígitos fraccionarios y significativos respectivamente.

También hablaremos de los métodos heredados de Object que son toString() y toLocaleString() que tienen un especial comportamiento con los números. Con el último haremos un generador de formato para presentar números con formato local de moneda o porcentajes.

Infinito y NaN son números del formato IEEE754

En este tema se expone como el formato IEEE754 representa los valores infinito y NaN y que utilidades tenemos en JavaScript para manejarlos. Una cuestión que resolveremos es dónde empieza Infinity. También se dedica el tema a los enteros, explicando con detalle el método parseInt() para convertir a entero.

En JavaScript la operaci'ón 1.7 - 1.1 no da exactamente 0.6

En este tema entramos en la materia que me interesaba, saber por ejemplo por qué 1.75 - 1.125 da exactamente 0.625 y sin embargo 1.7 - 1.1 no da el resultado exacto 0.6. Esto tiene que ver con la precisión del formato IEEE754, donde el espaciado de los números es un concepto básico que debemos conocer.

Comentaremos sobre la comparación de números, los dígitos significativos y también sobre la cantidad total de números decimales que podemos representar en dicho formato.

El formato IEEE754

Convertidor formato IEEE754

El Formato IEEE754 es el que usa JavaScript para representar los números decimales. Se basa en un formato de coma flotante en un registro de 64 bits. Se presenta un convertidor IEEE754 con el que podemos extraer dicho formato de un número decimal y que nos servirá en temas posteriores para resolver dudas sobre ejemplos concretos.

Generador de formato local del método toLocaleString()

Los números decimales se tienen que representar en binario. Por lo tanto hay que saber al menos como convertir un número decimal en binario y al revés. Presentaremos un convertidor binario-decimal para practicar estas conversiones. Como la representación binaria de un número decimal siempre estará limitada a un número determinado de bits, eso introducirá limitaciones en la precisión que hay que conocer.

Otro tema que afecta a los números tiene que ver con los cálculos de operaciones aritméticas. Se presenta una calculadora binaria para realizar las operación básicas y que nos servirá en temas posteriores para resolver algunas dudas.

Los números en JavaScript

Siguiendo con el repaso de conceptos básicos de JavaScript y al mismo tiempo estudiando las nuevas incorporaciones de ES6 (EcmaScript 2015), ya iba siendo hora de enfrentarme con los números en JavaScript.

Y es que si intentamos entender todo lo que pasa con los números en JavaScript tenemos que conocer algo más que la sintaxis del lenguaje y los métodos del objeto Number. Es necesario conocer la representación binaria de los números, el formato IEEE754 y la limitaciones de la precisión. Es también necesario saber como dicho formato lleva a cabo el redondeo buscando la representación de un un número en dicho formato. Este primer tema será una introducción para luego continuar con los siguientes desarrollando esos puntos.

Objeto de tipos para verificar argumentos de una función

JavaScript es débilmente tipado. Esto puede ser una desventaja cuando ejecutamos una función, pues no podemos asegurar que los tipos de los valores que se reciban sean los esperados. Se soluciona incorporando controles con typeof para ver si el argumento es del tipo esperado. No deja de ser un trabajo y código adicional que tenemos que incorporar en cada función y para cada paramétro que queramos verificar. Es una pena que JavaScript no tenga algo como si tiene TypeScript, donde la declaración function fun(a: number, b: string) obliga a que los argumentos tengan que ser de esos tipos.

Pero con ES6 y los parámetros por defecto o predeterminados podemos construirnos una función verificadora que lleve a cabo esa comprobación de forma automática. Para ello usaremos el código de la función obtenido con fun.toString(), parseando una cabecera como fun(a="", b=0) para deducir que los parámetros son de tipos string y number respectivamente, lo que se deduce de los tipos de los valores predeterminados. Con ello construiremos un objeto de tipos como el de la imagen, que nos servirá para verificar los tipos de los argumentos.

El método keys() recupera las claves de un objeto

El término iterar debemos entenderlo como repetir un mismo proceso sobre los propiedades de un objeto. Podemos, por ejemplo, recorrer todas las propiedades buscando áquellas cuyos valores sean tipos string y hacer algo con esos valores. Por definición los objetos creados directamente de Object no son iterables, pero otros como los Array si lo son, pues implementan un método Symbol.iterator(). Para iterar por un objeto hemos de recurrir a sus propios métodos, como Object.keys() que recupera un Array con las claves del objeto. Como todos los objetos derivan de Object estos métodos también se pueden aplicar a ellos, junto a la posibilidad de que implementen también el método Symbol.iterator().

Todos los objetos de JavaScript se constituyen con propiedades como parejas clave-valor

Las frases JavaScript está basado en objetos, Los objetos se relacionan a través de los prototipos y Los objetos contienen propiedades clave-valor podrían servir para identificar este lenguaje de programación. La última podría parecer innecesaria, pero describe la estructura de los objetos en JavaScript, dado que una propiedad es una entidad como una pareja clave-valor.

En este tema agrupamos todos los métodos que nos permiten crear y modificar propiedades como defineProperty(). Otros métodos como freeze() y seal() nos permitirán congelar y sellar respectivamente un objeto.

Todos los objetos de JavaScript tiene un __proto__ (prototipo)

Entender los prototipos de los objetos es imprescindible para manejarse bien con JavaScript. Por eso hemos agrupado en este tema todos los métodos que tienen que ver con los prototipos.

Podemos llegar a JavaScript desde otros lenguajes de programación que usan Programación orientada a objetos (POO). En ese caso podríamos decirnos lo siguiente: JavaScript, otro lenguaje basado en objetos, si conozco POO tendré bastante ventaja. Pero es una gran equivocación pensar así. JavaScript está basado en objetos, pero la relación entre ellos se produce a través de los prototipos. Y esto nada tiene que ver con POO, aunque la relación prototípica pueda simular bastante bien la POO.

El método toLocaleString() nos permite dar formato local a cadenas.

En Object hay algunos métodos básicos cuyo propósito es que puedan ser sobrescritos en las instancias, especialmente en los built-in como Array, Number o Date. Son los métodos del prototipo toString(), toLocaleString() y valueOf(). Con este último haremos un ejemplo de tipo de números romanos, evidenciándose para que sirve ese método. Con toLocaleString() podemos convertir a formato local tanto números como fechas.

Otro método que veremos es Object.is() que complementa las comparaciones de igualdad estricta === y con coerción ==. Explicaremos porque se aconseja siempre usar la comparación estricta.

Los objetos en JavaScript se relacionan a través de los prototipos

Conocer JavaScript pasa necesariamente por conocer los objetos y como se relacionan por medio de prototipos. La frase en JavaScript todo son objetos trata de sintetizar el hecho de que JavaScript es un lenguaje de objetos basado en prototipos, donde los objetos heredan de otros objetos y en última instancia del prototipo de Object (Object {}).

En este tema y los siguientes haré un repaso general de Object y sus métodos. Especialmente con la puesta al día de lo nuevo de ES6 relacionado con los objetos.


...Ver más en el histórico