Seleccionar página

Introducción

Una de los requisitos cada día más común es que nuestro código Javascript debe poder funcionar sin problemas tanto en el navegador como en el servidor con Node. Esto puede parecer en principio algo sencillo, pero lo cierto es que en ocasiones nos encontraremos con limitaciones difíciles de salvar: utilizamos el DOM del navegador, requerimos algún recurso, como una base de datos, que sólo tenemos disponible en el servidor. En otros casos nuestro programa se puedrá ejecutar sin demasiadas dificultades tanto en el cliente como en el servidor al ser agnóstico al contexto de ejecución.

Sobre la base de esta premisa, con este artículo iniciamos una serie dedicada a mostrar algunos aspectos que consideramos interesantes en la construcción de un módulo en Javascript. Como ejercicio (prácticamente es una excusa) hemos seleccionado un problema sencillo, pero que a su vez recoge una complejidad intrínseca del lenguaje: la creación de una función universal que permita comparar cualquier tipo de dato en Javascript.

Aunque pueda parecer que comparar dos valores es algo sencillo y común, lo cierto es que comparar valores en Javascript conlleva algunas dificultades que debemos conocer y manejar para evitar problemas. Comparar valores como números o cadenas no es muy difícil, pero la cosa se complica cuando se producen conversiones de tipo no previstas o cuando queremos trabajar con fechas, matrices o cualquier tipo de objeto. Durante esta serie de artículos vamos a ver paso a paso que tenemos que tener en cuenta para hacer una correcta comparación en Javascript, desde lo más sencillo, hasta lo más complicado y de esta forma analizaremos diferentes tipos de datos, su funcionamiento y algunas de sus características.

Al necesitar que se ejecute en el navegador tendremos que tener en cuenta la compatibilidad entre versiones, por lo que nos hemos marcado como premisa que debe funcionar en cualquier navegador con un soporte mínimo de EcmaScript 5.1, es decir, desde Internet Explorer 9 en adelante. Las versiones anteriores podrían ser utilizadas por medio de algún polyfil, pero esto se escapa de nuestro alcance inicial. También debe funcionar en cualquier versión de Node.

Para empezar vamos a ver cómo tenemos que construir nuestro módulo para que pueda funcionar tanto en el navegador como en Node, ya que ambos sistemas son muy diferentes. Aunque existen soluciones como Browserify, y que la incorporación de los nuevos módulos de EcmaScript 6 abre nuevas posibilidades, vamos a tener una aproximación muy sencilla, evitando dependencias y que realmente funciona.

Aislar el código del módulo

El primer paso que vamos que dar para construir nuestro módulo es aislar las partes privadas de nuestro código. Más adelante veremos como publicar las funciones que nos interesan, ahora vamos a ver lo contrario, como proteger aquellos elementos que no tienen interés para otros.

Node

Una característica interesante que ofrece Node es que en los módulos las variables o funciones definidas dentro del fichero del módulo son locales al mismo y no se crean en el contexto global. Dicho de otra forma, si en nuestro fichero esequal.js escribimos algo como:

var name = "esequal";

y en Node cargamos este fichero con

require("./esequal");

se habrá creado una variable con el nombre “name” en el contexto del módulo, pero el espacio global o del programa que hace uso del módulo no ha sido alterado. Por defecto el contenido de los módulos en Node es privado al módulo.

Navegador

En el navegador no tenemos un mecanismo similar y por defecto las variables o funciones definidas en un fichero .js se crean en el contexto global. Por ello es muy facil que puedan producirse con facilidad conflictos y problemas con los elementos de otras librerías. Es decir, si cargamos ese fichero esqual.js en el navegador con:

como resultado tendremos una variable global con el nombre name.

Para evitar el problema en el navegador debemos ser capaces de controlar el contexto en el que se definen las variables y funciones locales a nuestro módulo y exponer en el contexto global sólo aquello que deseamos exportar. Parar conseguir este aislamiento debemos crear una clausura, que evitará que definamos variables o funciones globales, además de poder indicar que vamos a trabajar en modo estricto sin afectar a otros ficheros .js que se definan con posterioridad a la carga de nuestro módulo. Por ello debemos crear una función de este tipo:

(function () {
    "use strict";
    var name = "esequal";
})();

El código se ejecutará directamente, pero lo que definamos dentro de esta función queda definido sólo para este contexto, manteniéndose en contexto global sin ninguna alteración.

Exponer funciones

Ahora vamos a centrarnos en exponer la parte del código que sí nos interesa que sea utilizado fuera de nuestro módulo, es decir, vamos a ver como hacer público la función o funciones que nuestro módulo ofrece al resto de código.

Node

En Node debemos utilizar module.exports para exponer una función de nuestro módulo.

"use strict";

function equal(a, b) {
}

module.exports = equal;

De esta forma la función equal está disponible si cargamos el modulo con:

var esqual = require("./esequal");

Navegador

En el navegador vamos a exponer en el contexto global una función por medio de este conjunto de instrucciones:

En este caso el this que pasamos a la clausura corresponderá de forma habitual a window, por lo que cuando escribimos root.equal lo que estamos haciendo es definir una propiedad window.equal. De esta forma se crea una variable global que apunta a la función que queremos exponer.

La solución general

Si unimos todo lo que hemos visto hasta ahora, obtendremos una función que puede función que puede funcionar como un módulo en el navegador y en Node. El resultado es un código similar a este:

Primera versión de esqueal.js en GitHub

Como se puede observar, es un esquema bastante sencillo y que podemos utilizar con seguridad tanto en Node como en el navegador. Podremos utilizarlo con require("esequal.js") o con <script src="esequal.js"></script> sin ningún problema.

Conclusiones

Es cierto que existen otras soluciones para la gestión de módulos en el navegador, como Browserify, y que la incorporación de los nuevos módulos de ES6 abre una nueva vía de homogenización entre la programación en el cliente y en el servidor, pero una solución como la que hemos expuesto es realmente sencilla de implementar, la podemos utilizar sin necesidad de librerías externas en navegadores y funciona en versiones de modernas y antiguas de los navegadores y en Node sin necesidad de cambiar nada.

En los próximos artículo vamos a utilizar este esquema base para construir una función universal para comparar cualquier tipo de datos en Javascript. De momento ya hemos dado nuestro primer paso.

Novedades

HTTP2 para programadores. Enviar mensajes del servidor al cliente con Server Sent Event (sin WebSockets)

HTTP2 para programadores. Enviar mensajes del servidor al cliente con Server Sent Event (sin WebSockets)

En esta charla, organizada por MadridJS, Pablo Almunia nos muestra cómo la mayoría de nosotros cuando oímos hablar por primera vez de HTTP2 nos ilusionamos con las posibilidades que presumiblemente se abrían para el desarrollo de soluciones web avanzadas y cómo muchos nos sentimos defraudados con lo que realmente se podía implementar.

En esta charla podemos ver cómo funciona el HTTP2, que debemos tener en cuenta en el servidor para hace uso de este protocolo y, sobre todo, cómo podemos enviar información desde el servidor al cliente de forma efectiva y fácil. Veremos con detenimiento cómo por medio de los Server-Sent Events (SSE) podemos recibir en el cliente datos enviados desde el servidor sin utilizar websocket, simplificando enormemente la construcción de aplicaciones con comunicación bidireccional.

Observables en Javascript con Proxies

Observables en Javascript con Proxies

En esta charla, organizada por MadridJS, Pablo Almunia nos habla de la observación reactiva de objetos en Javascript por medio de Proxy. Se describe paso a paso cómo funcionan los Proxies y en que casos pueden ser nuestro mejor aliado. Veremos que no hay que tenerles miedo, son bastante sencillos de utilizar, y nos ofrecen una gran abanico de posibilidades.

Aplicaciones JAMStack, SEO friendly y escalables con NextJS

Aplicaciones JAMStack, SEO friendly y escalables con NextJS

En esta charla de Madrid JS, Rafael Ventura nos describe las funcionalidades clave de NextJS, nos muestra en vivo cómo desarrollar una completa aplicación JAMStack con Server Side Rendering (SSR) y Static Site Generation (SSG) y termina mostrando como publicar esta aplicación en Vercel.

Stencil JS: mejora el Time To Market de tu producto, por Rubén Aguilera

Stencil JS: mejora el Time To Market de tu producto, por Rubén Aguilera

En esta charla Rubén Aguilera nos cuenta los problemas que tienen muchas empresas a la hora de sacar productos accesibles, vistosos y usables en el Time To Market que requiere Negocio y cómo podemos minimizar este tiempo gracias al DevUI con StencilJS para adecuar una aplicación de Angular a las exigencias del mercado en tiempo record.

breves

Descrubir algunas características de console

En el día a día nos encontramos muy a menudo utilizando console. Es una navaja multiusos que nos facilita la vida a la hora de depurar nuestro código. La mayoría de nosotros ha utilizado console.log(), pero tiene otras muchas funcionalidades.

Matrices dispersas o sparse arrays en JS

Una característica que puede producir algunos problemas, si no lo tenemos en cuenta, es la posibilidad de tener matrices con huecos, es decir, con algunos de sus elementos sin definir. Es lo que se suele denominar una matriz dispersa o sparse array. Veamos cómo trabajar con esta características de las matrices.

Operadores de bits usados con asiduidad

Cada día más a menudo podemos encontrar operadores binarios utilizados como formas abreviadas de algunas operaciones que de otra forma sería algo menos compactas y, quizás, más comprensibles. Veamos algunos casos en detalle.