Objetivos

Las funciones constituyen una de las claves necesarias para comprender javascript a fondo. Al finalizar la unidad entenderás por qué son objetos de primera clase, qué es un callback, las distintas maneras de definir funciones: como declaraciones y como expresiones,  la diferencia sutil entre parámetros de una función y argumentos, qué son y como se usan los parámetros intrínsecos arguments y this, las distintas maneras de invocar una función y su efecto sobre el parámetro intrínseco this, y los importantes conceptos de scope y closure.

Videos de la unidad

A lo largo de la unidad se irán presentando diferentes videos. Aquí te ofrecemos la lista de reproducción con todos los videos de la unidad, para que los tengas más a mano.

Funciones como objetos de primera clase

Todo lo que puede hacerse con un objeto en javascript, puede hacerse con una función. Ya que en javascript las funciones son un objeto más que tienen la peculiaridad de poder ser invocadas para realizar algún cómputo y, posiblemente, para devolver un resultado.

Así que, como con cualquier otro objeto,  podemos

  • asignar funciones a variables,
  • declararlas como literales,
  • pasarlas como argumentos de una función (callbacks),
  • devolverlas como resultado de una función y
  • añadirle los atributos (propiedades) que deseemos.

Y esto es lo que significa que las funciones en javascript son objetos de primera clase. En el siguiente vídeo te mostramos con detalle las implicaciones de que las funciones sean objetos.

Frecuentemente se dice que javascript es un lenguaje funcional. Y es cierto, pero con matices. Es funcional porque la función es el elemento fundamental del lenguaje. Pero esto no significa que al programar con javascript estemos haciendo programación funcional. Para hacer programación funcional hemos de programar siguiendo las reglas estrictas del estilo funcional. Y eso solo se puede hacer siendo muy consciente y conociendo a fondo los fundamentos del estilo. Ahora bien, si un programador desea usar este estilo de programación, javascript es una lenguaje muy adecuado para ello.
El hecho de que las funciones sean objetos abre la puerta del mundo de la programación funcional en javascript. Este estilo de programación se basa en la construcción de programas mediante definición y combinación de funciones puras. Una función pura es aquella cuyo resultado depende únicamente de sus argumentos, y no lleva a cabo ningún efecto colateral, asegurando que su ejecución no hace más que calcular y devolver el resultado. La programación funcional mejora la testabilidad del software, reduce errores en la programación paralela y facilita la modularidad de los programas. No obstante exige un cambio nada trivial en la forma de pensar del programador.

Definiendo funciones

En javascript podemos definir las funciones de distintas maneras:

  • mediante declaración, que da lugar a funciones con nombre,
  • mediante expresión de funciones, que da lugar a funciones anónimas y
  • mediante el uso del constructor del objeto Function.

En la versión ES6 del lenguaje (javascript 2015) se han añadido dos maneras más:

  • mediante funciones arrow,
  • mediante generadores.

En el siguiente vídeo mostramos con detalle los 3 primeros métodos. Las funciones arrow y los generadores los veremos en la unidad dedicada a las mejoras introducidas en la versión ES6 de javascript.

Argumentos y parámetros

Argumentos y parámetros son dos palabras que solemos utilizar de manera equivalente cuando hablamos de los valores que pasamos a las funciones entre paréntesis y que serán utilizados de alguna manera cuando sean ejecutadas. No obstante, para entender el mecanismo que usa javascript para tratar dichos valores es importante distinguir entre ambos conceptos.

En javascript hablamos de parámetros cuando estamos definiendo la función, y de argumentos cuando estamos invocando la función. Lo curioso de javascript es que el número de parámetros no tiene por que ser igual al de argumentos. Podemos pasar cualquier número de argumentos a una función y acceder a ellos en su cuerpo mediante el parámetro implícito arguments, un array cuyos elementos son los argumentos que pasamos al invocar la función.

Estrictamente hablando arguments no es un array, pero es algo muy parecido a efectos prácticos, ya que consiste en un conjunto ordenado de valores que se acceden mediante un índice.

En el caso de que  hayamos declarado parámetros al definir la función, los argumentos se asignarán a variables locales de la función con el  nombre de los parámetro y siguiendo el mismo orden. Pero si no los hemos definidos o el nº de argumentos excede al de parámetros, la invocación a la función sigue siendo correcta y el intérprete no da ningún error.

Todo esto se explica con detalle en el siguiente video:

El parámetro implícito «this» y la invocación de funciones

El parámetro implícito «this» es, sin lugar a dudas, uno de los «misterios» del javascript que provoca más errores y confusiones a los programadores. La razón principal es que, a pesar de estar relacionado con la programación orientada a objetos, no funciona de la misma manera que en la mayor parte de los lenguajes orientados a objetos basados en clases, como Java o C++. Y los programadores que comenten la «imprudencia» de pensar en «this» como si estuvieran en Java o C++ lo pagan caro.

En este vídeo diseccionamos los mecanismos de construcción del objeto «this» para que deje de ser un «misterio» y seas capaz de interpretar correctamente el valor que toma en cada caso. La clave, como verás, está en comprender que se trata de un parámetro implícito (igual que arguments) de las funciones, y que su valor depende de la forma en que esta se invoque.

Por ello veremos las 4 formas que tenemos en javascript de invocar funciones y como afectan a la construcción de this:

  • invocación normal,
  • como método de un objeto,
  • como un constructor de objeto y,
  • mediante los métodos del objeto función apply() y call()

En los siguientes vídeos explicamos con detalle el comportamiento del parámetro implicito this según la forma en que se invoque la función.

El parámetro implicito «this».

Invocando funciones con los métodos «apply()» y «call()»

Fijando el contexto de la función con el método «bind()»

Como hemos visto, this es un parámetro implícito de las funciones cuyo valor depende de la forma en que estas se invoquen. En ocasiones, por ejemplo cuando definimos callbacks al registrar eventos con addEventListener(), el valor de this que «llega» al callback no es el que necesitamos para que nuestro programa funcione.

En estos casos podemos usar el método bind() del objeto Function, el cual crea una copia de la función con la peculiaridad de que el parámetro implícito this de esta copia se vincula, independientemente de como se invoque la función,  al objeto que se pasa como argumento de bind().

 Clausuras

Las clausuras son una de las características de javascript más utilizadas y menos comprendidas a la vez. En esencia una clausura no es más que un mecanismo que permite a una función acceder a todos los objetos declarados en cualquier función externa a la función en cuestión. Lo interesante es que, siempre que exista alguna referencia que apunte a la función en cuestión, este acceso sigue siendo posible. Incluso cuando haya finalizado la ejecución de dichas funciones externas.

Las clasusuras simplifican la resolución de muchos problemas, especialmente aquellos en los que deseemos reutilizar funciones que tengan que mantener algún estado y dichos estados deban ser independiente en cada ejecución. De hecho uno de los problemas que resuelven es el de la encapsulación y protección de datos, de la misma forma que los lenguajes de orientados a objetos basados en clases hacen con los atributos privados.

En el siguiente vídeo te contamos las claves para dominar las clausuras.

Qué hemos aprendido

  • Las funciones son un elemento fundamental para dominar javascript, pues todo, incluso la creación de objetos, se basa en ellas.
  • Las funciones son objetos y como tales se pueden declarar como literales, asignar a variables, pasarlas como argumentos de otras funciones, ser devueltas como resultados de otras funciones y añadirle atributos.
  • Existen varias formas para definir funciones, mediante declaración, mediante expresión y usando el constructor del objeto Function.
  • Los argumentos y los parámetros de las funciones en javascript, aunque por abuso del lenguaje se confunden, son cosas distintas; los argumentos se pasan en la invocación y los parámetros se definen en la declaración de las funciones.
  • Podemos invocar a las funciones de distintas maneras; normalmente, como métodos de objetos y como constructores de objetos con el operador new, en cada caso el parámetro inplícito «this» se fija de una forma distinta. También podemos invocar a las funciones con los métodos call() y apply() que nos permite indicar cual será el objeto que se vincule al parámetro «this».
  • El método «bind()» de las funciones hace una copia de las mismas con la peculiaridad de que el parámetro «this» será vinculado al objeto que se le pase como argumento con independencia de la manera en que invoquemos dicha copia.
  • Las clausuras son un mecanismo mediante el cual toda función pueden acceder a variables y objetos declarados en funciones externas a ellas que estén en su mismo scope. Son muy utiizadas en javascript, a veces sin saber siquiera que existen y sin conocer su funcionamiento.