Seleccionar página
Recientemente nos hemos encontrado con la necesidad de identificar si una determinada función es una función nativa del lenguaje Javascript o ha sido creada por código. La cuestión parece sencilla, pero cuando nos ponemos a pensar como resolverlo vemos que en principio las funciones y métodos escritos por nosotros en Javascript y los proporcionados con por el lenguaje no se diferencian a primera vista. Las funciones nativas se pueden incluso reescribir por otras nuestras, por lo que no tienen ningún privilegio o diferencia que podamos observar fácilmente.

Ya nos enfrentamos a un problema similar cuando nos preguntamos cómo diferenciar arrow function de function. En esa ocasión descubrimos dos formas de actuar, analizando el prototipo (que finalmente resultó infructuosa) y analizando la cadena devuelta por .toString()

Lamentablemente no hay nada identificable en la cadena de prototipos para localizar las funciones nativas. Es cierto que las funciones nativas no tienen prototype, ya que no pueden ser utilizadas como constructores, pero tampoco lo tienen los métodos de nuestras clases o las arrow function. Por aquí no vamos a encontrar la solución.

Por lo tanto, no nos queda más remedio que analizar el código devuelto por .toString(). Comprobamos en diferentes navegadores y motores que siempre incluye la cadena [native code]:

console.log (parseInt.toString ());
 

function parseInt() { [native code] }

Por lo tanto, con una pequeña comprobación tenemos un sencillo medio para identificar si una función es nativa o está construida por código.

function isNative(fn) {
  return fn.toString().includes('[native code]');
}

Como primera aproximación no está mal, pero cualquier código que contenga el texto '[native code]' dará positivo. Es cierto que no es un texto muy habitual, pero nada impide que ese texto aparezca en el cuerpo de una función. Por ejemplo, si preguntamos si la propia función isNativeFunction() es nativa, obtendremos un falso positivo:

console.log(isNativeFunction(isNativeFunction)); // true

Con poco esfuerzo adicional podemos hacer una comprobación un poco más completa, incluyendo si es una función, las llaves y los posibles espacios en blanco entre los elementos, el final de la cadena y el propio nombre de la función.

function isNativeFunction (fn) {
  const str = fn.toString ();
  return typeof (fn) === 'function' &&
         /\{\s*\[\s*native code\s*\]\s*\}$/.test (str) &&
         str.includes (fn.name);
}
 

Ahora se puede ejecutar una batería de pruebas con diferentes opciones y comprobar que todo funciona correctamente:

console.assert (!isNativeFunction (function () {}));
console.assert (!isNativeFunction (function* () {}));
console.assert (!isNativeFunction (() => {}));

class C {m() {}}
console.assert (!isNativeFunction (C));
console.assert (!isNativeFunction (C.prototype.m));
console.assert (!isNativeFunction (isNativeFunction));
console.assert (!isNativeFunction ({
  toString () {
    return `function x { [native code] }`;
  }
}));
console.assert (!isNativeFunction (
  function x () {
    return "function x { [native code] }";
  }
));

Pero, ¿es seguro hacer uso de .toString()?. Lo cierto es que el estándar Javascript ha sido un poco confuso en cuanto a lo que tiene que devolver la función .toString() en el caso de las funciones. No obstante, todos los navegadores y motores de Javascript han realizado una implementación muy similar, aunque con mínimas variaciones.

Recientemente se ha propuesto una revisión de la estandarización de toString() para que no tenga ambigüedades, esta propuesta se encuentra en estos momentos en Stage 4, es decir, preparado para formar parte del estándar en la próxima edición. Por ello podemos estar bastante tranquilos en su utilización.

Aunque pueda parecer una solución un poco indirecta, lo cierto es que funciona. Podemos estar tranquilos al consultar el código de la función para analizar su tipología. Este es un recurso que tenemos a nuestra disposición y con la estandarización de facto y la nueva revisión de la estandarización formal de ECMAScript es seguro utilizarlo.

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.