Función clase vs fábrica: explorando el camino a seguir

Discover Functional JavaScript fue nombrado uno de los mejores libros nuevos de programación funcional por BookAuthority .

ECMAScript 2015 (también conocido como ES6) viene con la classsintaxis, por lo que ahora tenemos dos patrones en competencia para crear objetos. Para compararlos, crearé la misma definición de objeto (TodoModel) como clase,y luego como función de fábrica.

TodoModel como clase

class TodoModel { constructor(){ this.todos = []; this.lastChange = null; } addToPrivateList(){ console.log("addToPrivateList"); } add() { console.log("add"); } reload(){} }

TodoModel como función de fábrica

function TodoModel(){ var todos = []; var lastChange = null; function addToPrivateList(){ console.log("addToPrivateList"); } function add() { console.log("add"); } function reload(){} return Object.freeze({ add, reload }); }

Encapsulamiento

Lo primero que notamos es que todos los miembros, campos y métodos de un objeto de clase son públicos.

var todoModel = new TodoModel(); console.log(todoModel.todos); //[] console.log(todoModel.lastChange) //null todoModel.addToPrivateList(); //addToPrivateList

La falta de encapsulación puede crear problemas de seguridad. Tome el ejemplo de un objeto global que se puede modificar directamente desde Developer Console.

Cuando se usa la función de fábrica, solo los métodos que exponemos son públicos, todo lo demás está encapsulado.

var todoModel = TodoModel(); console.log(todoModel.todos); //undefined console.log(todoModel.lastChange) //undefined todoModel.addToPrivateList(); //taskModel.addToPrivateList is not a function

esta

thisLos problemas de pérdida de contexto siguen ahí cuando se usa la clase. Por ejemplo, thisestá perdiendo contexto en funciones anidadas. No solo es molesto durante la codificación, sino que también es una fuente constante de errores.

class TodoModel { constructor(){ this.todos = []; } reload(){ setTimeout(function log() { console.log(this.todos); //undefined }, 0); } } todoModel.reload(); //undefined

o thisestá perdiendo contexto cuando el método se usa como devolución de llamada, como en un evento DOM.

$("#btn").click(todoModel.reload); //undefined

No hay tales problemas cuando se usa una función de fábrica, ya que no se usa thisen absoluto.

function TodoModel(){ var todos = []; function reload(){ setTimeout(function log() { console.log(todos); //[] }, 0); } } todoModel.reload(); //[] $("#btn").click(todoModel.reload); //[]

esta función y la flecha

La función de flecha resuelve parcialmente los problemas de thispérdida de contexto en las clases, pero al mismo tiempo crea un nuevo problema:

  • this ya no pierde contexto en funciones anidadas
  • this está perdiendo contexto cuando el método se usa como devolución de llamada
  • La función de flecha promueve el uso de funciones anónimas.

Refactoré el TodoModeluso de la función de flecha. Es importante notar que en el proceso de refactorización a la función de flecha podemos perder algo muy importante para la legibilidad, el nombre de la función. Mira por ejemplo:

//using function name to express intent setTimeout(function renderTodosForReview() { /* code */ }, 0); //versus using an anonymous function setTimeout(() => { /* code */ }, 0);

Discover Functional JavaScript fue nombrado uno de los¡Los mejores libros nuevos de programación funcional de BookAuthority !

Para obtener más información sobre la aplicación de técnicas de programación funcional en React, eche un vistazo a Functional React .

Aprenda React funcional , de una manera basada en proyectos, con Arquitectura funcional con React y Redux .

Seguir en Twitter