Hola Habr!
Hoy comenzaremos a hablar sobre un tema muy importante: la programación funcional. La importancia de FP en el desarrollo web moderno es difícil de sobreestimar. La arquitectura de cualquier proyecto moderno a gran escala incluye bibliotecas de funciones definidas por el usuario, y habrá preguntas obligatorias sobre FI en la entrevista a cualquier nivel.
Introducción a la programación funcional
La programación funcional (FP) es una forma de organizar el código escribiendo un conjunto de funciones.
EcmaScript, al ser un lenguaje de programación multi-paradigmático, implementa, entre otros, un paradigma funcional. Esto significa que las funciones en ES son datos y pueden pasarse a funciones, devolverse de funciones y pueden aceptar funciones por sí mismas. Es decir Las funciones en ES son
funciones de primera clase .
Las siguientes definiciones se derivan de esto:
Argumento funcional (funarg) : argumento cuyo valor es una función.
Una función de orden superior (FWP, high-order-funtion, hof) es una función que acepta funciones como argumentos.
Funciones con un valor funcional (Funciones con funciones) : una función que devuelve una función.
Todos estos tipos de funciones se combinan condicionalmente en funciones de la primera clase y, como se deduce de la definición anterior, en ES todas las funciones son objetos de la primera clase.
Funciones puras: el ideal de la programación funcional
Funciones puras (PF) : siempre devuelve un resultado previsto.
Propiedades de PF:
- El resultado de la ejecución de PF depende solo de los argumentos pasados y del algoritmo que implementa PF
- No use valores globales
- No modifique valores externos o argumentos pasados
- No escriba datos en archivos, bases de datos ni en ningún otro lugar.
Un ejemplo de una función pura:
const add = (x,y) => x+y;
Un buen ejemplo de impureza de función es:
var first; var second; function testFn() { var a = 10; first = function() { return ++a; } second = function() { return --a; } a = 2; first();
¡Imagínese lo complicado que es escribir pruebas para este ejemplo y cuánto simplifica para funciones puras!
Las funciones impuras se caracterizan por un estado externo variable en el tiempo que complica el mantenimiento, la comprensión y las pruebas de código.
Por el contrario, las funciones puras son siempre legibles, comprobables, simplifican la paralelización de los cálculos y son fáciles de reutilizar.
Creo que notó que en los ejemplos sobre funciones puras, cambié a la sintaxis ES6. Esto se hizo deliberadamente. Esta sintaxis de funciones se llama "funciones de flecha", pero de hecho es una implementación de abstracción matemática, inventada hace mucho tiempo. Sobre esto más allá.
Lambda - funciones
Esto es lo que se llama esta forma de escritura de flecha en matemáticas y algunos otros lenguajes de programación. La programación funcional está muy relacionada con el tapete. análisis, así que no te sorprendas.
El término cálculo Lambda fue introducido en la década de 1930 por Alonzo Church. En esencia, el cálculo lambda no es más que una forma formal de describir una ecuación matemática. Más detalles
aquí .
En ES, una función lambda a menudo implementa un cierre:
const add = x => y => x + y;
Corto y conciso. La función add es una lambda que toma un argumento x, lo almacena en un cierre y devuelve una función.
Compare con este código:
funtion add(x) { return function (y) { return x + y; } }
Obviamente, la primera opción se ve mejor.
Inmunidad
Inmutable (inmutable, inmunidad) es un objeto cuyo estado no se puede cambiar después de la creación. El resultado de cualquier modificación de dicho objeto siempre será un objeto nuevo, mientras que el objeto antiguo no cambiará.
La inmutabilidad es el grial de oro de la programación funcional.
Considere un ejemplo:
const impureAddProp = (key, value, object) => { object[key] = value;
Como puede ver, en este ejemplo, mutamos el objeto Usuario al agregarle una propiedad. Ahora el objeto Usuario es una especie de "estado compartido" para la función impureAddProp y otras funciones que lo mutarán. Este enfoque es más difícil de probar porque Al cambiar cualquier función que interactúa con un estado compartido, siempre se deben tener en cuenta los posibles errores en otras funciones.
Desde el punto de vista de la programación funcional, sería correcto:
const pureAddProp = (key, value, object) => ({ ...object, [key]: value }); const User= { name: 'Alex' }; const Admin= pureAddProp ('isAdmin', true, User);
Por lo tanto, el objeto Usuario permanecerá sin cambios. Estamos modificando una copia de los datos, que siempre es segura.
Conclusión
Hoy hemos examinado varios conceptos teóricos importantes. Nos familiarizamos con las funciones puras, la forma lambda de las funciones de grabación y el concepto de inmutabilidad en fp. Sin embargo, este artículo es una especie de introducción. Las principales ideas, técnicas y "partes difíciles" de la programación funcional se encontrarán en los siguientes artículos.
La programación funcional es implementada por muchas bibliotecas. Esto es rambda, y lodash, y muchos otros. En un proyecto real, usted, por supuesto, los usará. Bajo el capó de cualquier biblioteca, seguirá habiendo el mismo JavaScript nativo, por lo que en los siguientes artículos analizaremos el FP, implementando todos sus conceptos en JS nativo.
Postdata
Comenzando a escribir artículos, tenía en mente el siguiente plan:
- escribir traducciones de interesantes artículos en inglés
- para resaltar varias áreas relevantes en JS (conceptos clave, OOP en términos de especificaciones EcmaScript, patrones, programación funcional).
Hasta la fecha, ya se han escrito artículos principales en tres áreas:
- this y ScopeChain en EcmaScript : aquí describí conceptos clave de la especificación como el contexto de ejecución, la palabra clave this y la propiedad de contexto ScopeChain (cadena de alcance). En el marco de esta dirección, mi artículo sobre el entorno léxico y el cierre se publicó literalmente hoy.
- Una mirada de EcmaScript a la teoría general de OOP : aquí se describió la diferencia entre la tipificación de clase estática y la organización dinámica de prototipos, el modelo de delegación y la tipificación de pato se desmontan
- Patrones elegantes en JavaScript moderno (serie de compilación de Bill Sourour en el ciclo) : aquí hay dos patrones que pueden ser útiles en algunas situaciones. Mi enfoque en términos de patrones es bastante simple: es mejor conocer tantos patrones como sea posible, porque tarde o temprano te será útil
Y ahora es el turno de la programación funcional. En el futuro, escribiré artículos en la continuación de cada una de estas áreas. Por ejemplo, el siguiente artículo tratará sobre los conceptos clave de OOP: encapsulación, abstracción, impurezas (y trazos), interfaces, etc. ... También planeo hablar sobre cómo se implementa OOP en ES bajo el capó, es decir. sobre las propiedades de [[Prototipo]], [[Clase]] y mucho más. Hable acerca de cómo v8 crea entidades e instancias de clases, funciones.
En los comentarios surgen muchas preguntas, así que me gustaría explicar los objetivos que establecí para mis artículos. No escribo tutoriales ni reviso la documentación. En mi opinión, esto no tiene sentido. No te aconsejo con ciertos instrumentos o patrones, su elección es totalmente tuya.
En los artículos, reviso los conceptos, cuento cómo se organizan debajo del capó (en mi opinión, esto mejora la comprensión de lo que escribimos y por qué escribimos de esta manera), o hablo de algunas cosas que amplían mis horizontes. En mi opinión esto es muy importante. Eche un vistazo a empresas como Yandex o Edadil, que constantemente hablan sobre algún tipo de ideas originales. O bien estos son mapas de bits en la reacción, entonces la aplicación vue está casi completamente en clases es6. La mayoría de los desarrolladores web nunca habrían pensado en tal cosa. Esto requiere una perspectiva amplia.
Yo mismo estudié y estudié la web de esta manera, es decir Después de leer un tutorial o un dock, trato de entender cómo funciona la herramienta descrita debajo del capó, para comprender su mecánica interna.
Hasta futuros artículos, amigos!