Funciones de orden superior en JavaScript

Si está aprendiendo JavaScript, debe haber encontrado el concepto de una "Función de orden superior". Esto puede parecer algo muy complicado, pero, de hecho, no lo es.

JavaScript es adecuado para la programación funcional porque admite el concepto de funciones de orden superior. Dichas funciones son ampliamente utilizadas en el lenguaje, y si programó en JS, entonces probablemente ya haya trabajado con ellas sin siquiera saberlo.



Para comprender completamente este concepto, primero debe comprender el concepto de programación funcional (programación funcional) y qué funciones son de primera clase (funciones de primera clase).

El material, cuya traducción publicamos, está destinado a principiantes, tiene como objetivo explicar el concepto de funciones de orden superior y demostrar cómo usarlas en JavaScript.

¿Qué es la programación funcional?


Si describe el concepto de programación funcional en palabras simples, resulta que este es un enfoque de programación, mediante el cual puede transferir funciones a otras funciones como parámetros y utilizar funciones como valores devueltos por otras funciones. Al estar involucrados en la programación funcional, diseñamos la arquitectura de la aplicación y escribimos código utilizando funciones.

Entre los lenguajes que admiten programación funcional se encuentran JavaScript, Haskell, Clojure, Scala y Erlang.

Funciones de primera clase


Si está aprendiendo JavaScript, es posible que escuche que en un lenguaje las funciones se tratan como objetos de primera clase. Esto se debe a que en JavaScript, como en otros lenguajes que admiten programación funcional, las funciones son objetos.

En particular, en JS las funciones se representan como objetos de un tipo especial; estos son objetos de tipo Function . Considere un ejemplo:

 function greeting() { console.log('Hello World'); } //   greeting();  //  'Hello World' 

Para probar que las funciones en JavaScript son objetos, podemos hacer lo siguiente, continuando con el ejemplo anterior:

 //     ,       greeting.lang = 'English'; //  'English' console.log(greeting.lang); 

Tenga en cuenta que si bien agregar sus propias propiedades a objetos estándar en JavaScript no causa mensajes de error, no se recomienda hacerlo. No debe agregar sus propias propiedades a las funciones. Si necesita almacenar algo en un objeto, es mejor crear un objeto especial para esto.

En JavaScript con funciones, puede hacer lo mismo que se puede hacer con entidades de otros tipos, como Object , String , Number . Las funciones se pueden pasar como parámetros a otras funciones. Dichas funciones, transferidas a otros, generalmente actúan como funciones de devolución de llamada (devoluciones de llamada). Las funciones pueden asignarse a variables, almacenarse en matrices, etc. Es por eso que las funciones en JS son objetos de primera clase.

Asignación de funciones a variables y constantes


Se pueden asignar funciones a variables y constantes:

 const square = function(x) { return x * x; } //   25 square(5); 

Las funciones asignadas a variables o constantes pueden asignarse a otras variables o constantes:

 const foo = square; //  36 foo(6); 

Pasar funciones como parámetros


Las funciones se pueden pasar como parámetros para otras funciones:

 function formalGreeting() { console.log("How are you?"); } function casualGreeting() { console.log("What's up?"); } function greet(type, greetFormal, greetCasual) { if(type === 'formal') {   greetFormal(); } else if(type === 'casual') {   greetCasual(); } } //  'What's up?' greet('casual', formalGreeting, casualGreeting); 

Ahora que sabemos cómo se comportan las funciones de primera clase, hablemos de las funciones de orden superior.

Funciones de orden superior


Las funciones de orden superior son funciones que funcionan con otras funciones, tomándolas como parámetros o devolviéndolas. En pocas palabras, una función de orden superior es una función que toma una función como argumento o devuelve una función como valor de salida.

Por ejemplo, las funciones de JavaScript incorporadas Array.prototype.map , Array.prototype.filter y Array.prototype.reduce son funciones de orden superior.

Funciones de orden superior en acción


Considere ejemplos de uso de funciones de orden superior integradas en JS y compare este enfoque con acciones similares sin usar tales funciones.

▍ Método Array.prototype.map


El método map() crea una nueva matriz, llamando, para procesar cada elemento de la matriz de entrada, la devolución de llamada se le pasa como un argumento. Este método toma cada valor devuelto por la devolución de llamada y lo coloca en la matriz de salida.

La función de devolución de llamada pasada a map() toma tres argumentos: element (elemento), index (índice) y array (matriz). Veamos algunos ejemplos.

Ejemplo no 1


Supongamos que tenemos una matriz de números y queremos crear una nueva matriz que contenga los resultados de multiplicar estos números por 2. Considere formas de resolver este problema utilizando funciones de orden superior y sin ellas.

Resolver un problema sin usar funciones de orden superior


 const arr1 = [1, 2, 3]; const arr2 = []; for(let i = 0; i < arr1.length; i++) { arr2.push(arr1[i] * 2); } //  [ 2, 4, 6 ] console.log(arr2); 

Resolver un problema usando un mapa de funciones de orden superior


 const arr1 = [1, 2, 3]; const arr2 = arr1.map(function(item) { return item * 2; }); console.log(arr2); 

Incluso puede reducir el volumen de este código si usa la función de flecha:

 const arr1 = [1, 2, 3]; const arr2 = arr1.map(item => item * 2); console.log(arr2); 

Ejemplo no 2


Supongamos que tenemos una matriz que contiene el año de nacimiento de algunas personas, y necesitamos crear una matriz que tenga su edad en 2018. Considere, como antes, la solución a este problema de dos maneras.

Resolver un problema sin usar funciones de orden superior


 const birthYear = [1975, 1997, 2002, 1995, 1985]; const ages = []; for(let i = 0; i < birthYear.length; i++) { let age = 2018 - birthYear[i]; ages.push(age); } //  [ 43, 21, 16, 23, 33 ] console.log(ages); 

Resolver un problema usando un mapa de funciones de orden superior


 const birthYear = [1975, 1997, 2002, 1995, 1985]; const ages = birthYear.map(year => 2018 - year); //  [ 43, 21, 16, 23, 33 ] console.log(ages); 

▍ Método Array.prototype.filter


El método filter() crea, en función de la matriz, una nueva matriz en la que caen los elementos de la matriz original, correspondiente a la condición especificada en la función de devolución de llamada pasada a este método. Esta función toma, como en el caso del método map() , 3 argumentos: element , index y array .

Considere un ejemplo construido de la misma manera que cuando considera el método map() .

Ejemplo


Supongamos que tenemos una matriz que contiene objetos cuyas propiedades almacenan información sobre el nombre y la edad de los representantes de un determinado grupo de personas. Necesitamos crear una matriz en la que solo habrá información sobre los representantes adultos de este grupo (aquellos cuya edad ha alcanzado los 18 años).

Resolver un problema sin usar funciones de orden superior


 const persons = [ { name: 'Peter', age: 16 }, { name: 'Mark', age: 18 }, { name: 'John', age: 27 }, { name: 'Jane', age: 14 }, { name: 'Tony', age: 24}, ]; const fullAge = []; for(let i = 0; i < persons.length; i++) { if(persons[i].age >= 18) {   fullAge.push(persons[i]); } } console.log(fullAge); 

Resolver un problema usando un filtro de función de orden superior


 const persons = [ { name: 'Peter', age: 16 }, { name: 'Mark', age: 18 }, { name: 'John', age: 27 }, { name: 'Jane', age: 14 }, { name: 'Tony', age: 24}, ]; const fullAge = persons.filter(person => person.age >= 18); console.log(fullAge); 

▍ Método Array.prototype.reduce


El método reduce() procesa cada elemento de la matriz mediante una devolución de llamada y pone el resultado en un único valor de salida. Este método toma dos parámetros: devolución de llamada y valor inicial opcional ( initialValue ).

Una devolución de llamada acepta cuatro parámetros: accumulator (acumulador), valor actual (valor actual), índice actual (índice actual), matriz de fuente (matriz fuente).

Si se proporciona el parámetro initialValue al initialValue , al principio del método, el accumulator será igual a este valor y el primer elemento de la matriz procesada se escribirá en currentValue .

Si el parámetro initialValue no se proporciona al método, el primer elemento de la matriz se escribirá en el accumulator y el segundo en currentValue .

Ejemplo


Supongamos que tenemos una serie de números. Necesitamos calcular la suma de sus elementos.

Resolver un problema sin usar funciones de orden superior


 const arr = [5, 7, 1, 8, 4]; let sum = 0; for(let i = 0; i < arr.length; i++) { sum = sum + arr[i]; } //  25 console.log(sum); 

Resolver un problema usando una función de orden superior reduce


Primero, considere usar el método reduce() sin darle un valor inicial.

 const arr = [5, 7, 1, 8, 4]; const sum = arr.reduce(function(accumulator, currentValue) { return accumulator + currentValue; }); //  25 console.log(sum); 

Cada vez que se llama una devolución de llamada con un currentValue pasado, es decir, el siguiente elemento de la matriz, su parámetro accumulator resulta que contiene los resultados de la operación anterior, es decir, lo que se devolvió de la función en la iteración anterior. Después de completar este método, el resultado final cae en la sum constante.

Ahora veamos cómo se verá la solución al problema si pasamos el valor inicial al método reduce() .

 const arr = [5, 7, 1, 8, 4]; const sum = arr.reduce(function(accumulator, currentValue) { return accumulator + currentValue; }, 10); //  35 console.log(sum); 

Como puede ver, el uso de una función de orden superior ha hecho que nuestro código sea más limpio, más conciso y más fácil de leer.

Crear funciones personalizadas de orden superior


Hasta ahora, hemos estado trabajando con funciones de orden superior integradas en JS. Ahora creemos nuestra propia función que funciona con otras funciones.

Imagine que JavaScript no tiene un método de matriz map() estándar. Podemos crear tal método nosotros mismos, que se expresará en el desarrollo de una función de orden superior.

Supongamos que tenemos una matriz de cadenas y nos gustaría crear una matriz con números, cada uno de los cuales representa la longitud de la cadena almacenada en algún elemento de la matriz original.

 const strArray = ['JavaScript', 'Python', 'PHP', 'Java', 'C']; function mapForEach(arr, fn) { const newArray = []; for(let i = 0; i < arr.length; i++) {   newArray.push(     fn(arr[i])   ); } return newArray; } const lenArray = mapForEach(strArray, function(item) { return item.length; }); //  [ 10, 6, 3, 4, 1 ] console.log(lenArray); 

En este ejemplo, creamos una función de orden superior mapForEach , que toma una matriz y una función de devolución de llamada fn . La función mapForEach matriz en un bucle y llama a la devolución de llamada fn en cada iteración de este bucle.

La devolución de llamada fn acepta el elemento de cadena actual de la matriz y devuelve la longitud de este elemento. Lo que devuelve la función fn se usa en el newArray.push() y entra en la matriz que mapForEach() devolverá. Esta matriz eventualmente se escribirá en la constante lenArray .

Resumen


En este artículo, hablamos sobre las funciones de orden superior y exploramos algunas de las funciones de JavaScript incorporadas. Además, descubrimos cómo crear sus propias funciones de orden superior.

En pocas palabras, se puede decir que la esencia de las funciones de orden superior son funciones que pueden tomar otras funciones como argumentos y devolver otras funciones como resultado de su trabajo. Trabajar con otras funciones en funciones de orden superior se ve igual que trabajar con cualquier otro objeto.

Estimados lectores! ¿Tienes que escribir tus propias funciones de orden superior?

Source: https://habr.com/ru/post/es428570/


All Articles