ES7: El operador ::bind

12528337624_f9437aca7d_b.jpg

Imagen de ewka2205

Aviso: El post explica funcionalidades experimentales que no se encuentran el estándar todavía y que puede que nunca lo estén.

Investigando un poco sobre las propuestas que se hacen al grupo de trabajo de EcmaScript he topado con una que me parece interesante traer aquí al blog y que quizá os interese.

Se trata de la posibilidad de incluir un nuevo operador que nos permita enlazar el contexto a la función que nosotros queramos. Lo han denominado coloquialmente operador bind.

En este post os hablo de qué trata, en qué casos nos podría ser útil y el estado en el que se encuentra actualmente su implementación final. Espero que os guste:

¿Qué es el operador bind?

El operador bind es una propuesta realizada al comité tc39 por Brian Terlson & Matthew Podwysocki, pensado como una forma de simplificar la manera en la que podamos enlazar, llamar o aplicar un contexto a una función determinada.

La idea es poder incluir un nuevo operador con una sintaxis de dobles dos puntos (::) para indicar que una función se tiene que ejecutar con un contexto determinado.

La propuesta es simplemente azúcar sintáctico sobre las funcionalidades ‘bind’, ‘apply’ y ‘call’ que ya encontramos actualmente en JavaScript, pero con una forma menos verbosa y más cómoda para los desarrolladores.

El operador me parece muy interesante porque, como veremos en el siguiente apartado, es buen paso a conseguir un código más legible, la nueva forma, permite realizar cómputos por medio de un operador que tiene mucho que ver al concepto de tuberías.

Otros lenguajes de programación, como Elixir, ya cuentan con un operador ‘pipe’ (‘|>’) que permite concatenar funciones de una forma cómoda e intuitiva, una forma muy parecida a la concatenación de acciones que existen en sistemas como unix con su operador ‘|’.

Para la gente que disfruta con la programación funcional, esta propuesta es una buena noticia – No es de extrañar pues, ya que Matthew Podwysocki es el creador de RxJs, la librería de programación funcional reactiva más famosa del mundo.

¿En qué casos nos puede ayudar?

Encadenando funciones

Y es que nos viene muy bien porque, aunque dentro de la comunidad ya nos las habíamos apañado para poder encadenar funciones, la solución de ‘::’ nos va a dejar las cosas más claras.

Imaginemos que queremos hacer una query contra el DOM y que nos queremos traer todos los elementos ‘li’ para hacer operaciones sobre la colección. El primer problema que tenemos es que la devolución del método ‘querySelectorAll’ es un objeto de tipo ‘NodeList’. Un objeto que no implementa los métodos iteradores ‘filter’, ‘map’ o ‘reduce’. Eso no es problema en JavaScript porque podemos hacer uso de ‘bind’, ‘apply’ y ‘call’:

const { map, filter } = Array.prototype;
const items = document.querySelectorAll('li');

const completedItems = filter.call(items, function(item) {
    return item.dataset.completed;
});
const titles = map.call(completeItems, function(item) {
    return item.textContent;
});

Lo que hemos hecho es extraer los métodos de Array y los hemos usado, llamándoles con el contexto que nos ha interesado. De esta manera, unos métodos que pertenecen a ‘Array’, pueden convertirse en genéricos y sernos de utilidad para tipos como el de ‘NodeList’.

Si contáramos ya con el nuevo operador, la idea quedaría más clara:

const { map, filter } = Array.prototype;
const items = document.querySelectorAll('li');

const titles = items
    ::filter(item => item.dataset.completed)
    ::map(item => item.textContent);

El código funciona igualmente, pero ahora se ve mucho más claro el encadenamiento de funciones que estamos haciendo. Hemos modularizado en funciones puras muy genéricas, que pueden usarse en varios contextos y encima el código queda reducido a esto.

Esto es solo un ejemplo. RambdaJS podría evolucionar a una librería que nos ofreciera tantos genéricos como la programación funcional necesitase. Al final se convertiría en una especie de librería de métodos virtuales.

Llamando a callbacks

Nos pasa mucho que queremos hacer uso de un método en una función callback de otro contexto y nos devuelve un bug por no haberlo hecho bien. Lo que hemos hecho antes de la llegada de ES6 es esto. Imaginemos que tenemos una librería de eventos:

import eventLib from 'eventLib';
const self = this;

eventLib.on('foo', function() {
    self.gotFoo();
});
Cacheabamos ‘this’ en ‘self’ y cuando se producía un callback, se ejecutaba la función de ‘self’ que estaba cacheada. Con el tiempo hemos ido mejorándolo y bueno. El problema podía ser resuelto con arrow function. Tener funciones anónimas no nos suele gustar así que acabamos teniendo algo parecido a esto:
eventLib.on('bar', this.gotBar.bind(this));
A mi me da mucha rabia tener que ensuciar tanto el código porque JS no haga algo bien, así que el operador bind podría hacer que el dolor sea menor. Las dos funciones anteriores serían lo mismo a estas con el azúcar sintáctico:
eventLib.on('foo', ::this.gotFoo);
eventLib.on('bar', ::this.gotBar);

¿En qué estado se encuentra la propuesta?

Cómo puse al principio del post, la propuesta se encuentra todavía en Stage 0, por lo que entiendo que todavía deberemos esperar bastante para que la inserten. La idea es que ES7 la lleve incluída, pero como digo, no se sabe.

Hay varias peticiones para que TypeScript lo incluya. Sabiendo que Brian Terlson es empleado de Microsoft, ganas nos les faltará, sin embargo, en Microsoft intentan no trabajar en funcionalidades que no se encuentran en Stage 1, así que también tendremos que esperar.

En cuanto a Babel, si se puede hacer uso de la funcionalidad, pero activando las funcionalidad experimentales, con lo que, el uso de ellas es responsabilidad vuestra. Yo sinceramente no las usaría en producción para evitarme disgustos, pero si podéis trastear con ellas.

Conclusión

El operador bind nos abre la posibilidad real de crear tuberías. Nos puede permitir crear métodos de extensión de una manera cómoda… el problema es que todavía nos quedará por verlo, sin embargo, es bueno ir conociendo lo que nos propone la comunidad para que entre todos hagamos fuerza por pedirlas y que las incluyan si nos interesan. Además, el conocerlas ya, hará menor nuestra fricción al aprendizaje cuando ya se encuentren incluidas en los navegadores.

Nos leemos 🙂

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s