Funciones de flecha en JavaScript

    Introducci贸n

    Si es un desarrollador de JavaScript, es posible que sepa que JavaScript se ajusta a la ECMAScript (ES) est谩ndares. Las especificaciones ES6, o ECMAScript 2015, hab铆an introducido algunas de las especificaciones revolucionarias para JavaScript, como funciones de flecha, clases, operadores de descanso y propagaci贸n, promesas, let y const, etc.

    En este tutorial, nos centraremos en las funciones de Arrow, que es muy confuso e intimidante para los principiantes de JavaScript.

    Sintaxis de la funci贸n de flecha

    Como sabemos, una funci贸n ES5 tiene la siguiente sintaxis:

    function square(a) {
        return a * a;
    }
    

    En ES6, podemos escribir la misma funci贸n con solo una l铆nea de c贸digo:

    let square = (a) => { return a * a; }
    

    Adem谩s, si el cuerpo de la funci贸n solo tiene una declaraci贸n que devuelve, podemos omitir las llaves {} y el return declaraci贸n:

    let square = (a) => a * a
    

    Adem谩s, si la funci贸n toma solo un par谩metro, incluso podemos omitir las llaves () alrededor:

    let square = a => a * a
    

    Por otro lado, si la funci贸n no toma ning煤n par谩metro, podemos escribirlo as铆:

    let results = () => { /* ...some statements */ };
    

    Tenemos que escribir menos c贸digo con esta sintaxis mientras proporcionamos la misma funcionalidad, lo que puede ayudar a ordenar y simplificar su c贸digo.

    La ventaja de esta sintaxis es m谩s notable cuando se usa en devoluciones de llamada. Entonces, un fragmento de c贸digo detallado y dif铆cil de seguir como este:

    function getRepos() {
        return fetch('https://api.github.com/users/Pharos.sh/repos')
          .then((response) => {
              return response.json();
          }).then((response) => {
              return response.data;
          }).then((repos) => {
              return repos.filter((repo) => {
                  return repo.created_at > '2019-06-01';
              });
          }).then((repos) => {
              return repos.filter((repo) => {
                  return repo.stargazers_count > 1;
              });
          });
    }
    

    se puede reducir a lo siguiente, utilizando las funciones de flecha:

    function getRepos() {
        return fetch('https://api.github.com/users/Pharos.sh/repos')
          .then(response => response.json())
          .then(response => response.data)
          .then(repos => repos.filter(repo => repo.created_at > '2019-06-01'))
          .then(repos => repos.filter(repo => repo.stargazers_count > 1));
    }
    

    Beneficios de las funciones de flecha

    Hay dos beneficios principales de usar las funciones de Arrow. Una es que es una sintaxis m谩s corta y, por lo tanto, requiere menos c贸digo. El principal beneficio es que elimina los varios puntos de dolor asociados con el this operador.

    Sin vinculaci贸n de ‘este’ operador

    A diferencia de otros lenguajes de programaci贸n orientados a objetos, en JavaScript (antes de las funciones de flecha) cada funci贸n defin铆a su referencia de this y depende de c贸mo se haya llamado a la funci贸n. Si tiene experiencia con lenguajes de programaci贸n modernos como Java, Python, C #, etc., el operador this o self dentro de un m茅todo se refiere al objeto que llam贸 al m茅todo y no a c贸mo se llama a ese m茅todo.

    Los programadores siempre se quejaron de que usar this es demasiado complicado en JavaScript. Causa una gran confusi贸n en la comunidad de JavaScript y provoca un comportamiento no deseado del c贸digo en algunos casos.

    Para comprender mejor el beneficio de las funciones de Arrow, primero comprendamos c贸mo this funciona en ES5.

    El operador ‘this’ en ES5

    El valor de this est谩 determinada por el contexto de ejecuci贸n de una funci贸n, que en t茅rminos simples significa c贸mo se llama a una funci贸n.

    Lo que aumenta la confusi贸n es que cada vez que se llama a la misma funci贸n, el contexto de ejecuci贸n puede ser diferente.

    Intentemos entenderlo con la ayuda de un ejemplo:

    function test() {
        console.log(this);
    }
    test();
    

    La salida de este programa ser铆a la siguiente en una consola de navegador:

    Window {...}
    

    Como llamamos test() desde el contexto global, el this palabra clave se refiere al objeto global que es un Window objeto en los navegadores. Cada variable global que creamos se adjunta a este objeto global Window.

    Por ejemplo, si ejecuta el siguiente c贸digo en una consola de navegador:

    let greetings="Hello World!";
    console.log(greetings);
    console.log(window.greetings)
    

    ser谩s recibido con ‘隆Hola mundo!’ dos veces:

    Hello World!
    Hello World!
    

    Como podemos ver la variable global greetings se adjunta al objeto global window.

    Tomemos un ejemplo diferente con una funci贸n constructora:

    function Greetings(msg) {
        this.msg = msg;
    };
    
    let greetings = Greetings('Hello World!');
    console.log(greetings);
    

    Obtendremos el siguiente mensaje en la consola:

    undefined
    

    lo cual tiene sentido porque estamos llamando Greetings() en window contexto y como el ejemplo anterior this se refiere al objeto global window y this.msg ha a帽adido msg propiedad a la window objeto.

    Podemos comprobarlo si ejecutamos:

    window.msg
    

    Seremos recibidos con:

    Hello World!
    

    Pero si usamos el new operador mientras crea el Greetings objeto:

    let greetings = new Greetings('Hello World!');
    console.log(greetings.msg);
    

    Seremos recibidos con:

    Hello World!
    

    Podemos ver el this operador no se refiere a la global window objetar esta vez. Es el new operador que hace esta magia. los new El operador crea un objeto vac铆o y hace que el this referirse a ese objeto vac铆o.

    Espero que ahora tenga una idea de nuestra declaraci贸n anterior.

    this depende de c贸mo se llame a una funci贸n.

    Tomemos otro ejemplo:

    let greetings = {
        msg: 'Hello World!',
        greet: function(){
            console.log(this.msg);
        }
    }
    
    greetings.greet();
    

    Si ejecutamos este c贸digo en una consola de navegador, nuevamente seremos recibidos con:

    Hello World!
    

    Porque piensas this no se refiri贸 a la window objetar esta vez?

    Enlace impl铆cito: this La palabra clave est谩 vinculada al objeto antes del punto.

    En nuestro ejemplo, se refiere a greetings objeto.

    Pero si asignamos la funci贸n de referencia greetings.greet a una variable:

    let greetRef = greetings.greet;
    greetRef();
    

    Seremos recibidos con:

    undefined
    

    驴Eso explica algo? 驴ReString haber llamado a una funci贸n en un contexto de ventana del ejemplo anterior?

    Como estamos llamando greetRef() en un window contexto, en este caso this se refiere a window objeto y sabemos que no tiene ning煤n msg propiedad.

    Tomemos un escenario m谩s complicado de usar una funci贸n an贸nima:

    let factory = {
        items: [5, 1, 12],
        double: function(){
            return this.items.map(function(item, index){
                let value = item*2;
                console.log(`${value} is the double of ${this.items[index]}`);
                return value;
            });
        }
    };
    

    Si llamamos factory.double() obtendremos el siguiente error:

    Uncaught TypeError: Cannot read property '0' of undefined
        at <anonymous>
        at Array.map (<anonymous>)
    

    El error indica que this.items no est谩 definido, lo que significa this dentro de la funci贸n an贸nima map() no se refiere a la factory objeto.

    Estas son las razones por las que llamamos a eso el valor de this est谩 determinada por el contexto de ejecuci贸n de una funci贸n. Hay ejemplos m谩s complicados sobre este punto de dolor que est谩 m谩s all谩 del alcance de este tutorial.

    Hay varias formas de solucionar este problema, como pasar el this contexto o uso bind(). Pero el uso de estas soluciones hace que el c贸digo sea complicado e innecesario.

    Afortunadamente, en ES6 las funciones de flecha son m谩s predecibles en t茅rminos de referencia a this palabra clave.

    El operador ‘this’ y las funciones de flecha en ES6

    Primero, convierta la funci贸n an贸nima dentro map() a una funci贸n de flecha:

    let factory = {
        items: [5, 1, 12],
        double: function(){
            return this.items.map((item, index) => {
                let value = item*2;
                console.log(`${value} is the double of ${this.items[index]}`);
                return value;
            });
        }
    };
    

    Si llamamos factory.double() seremos recibidos con:

    10 is the double of 5
    2 is the double of 1
    24 is the double of 12
    [10, 2, 24]
    

    Como podemos ver el comportamiento de this dentro de una funci贸n de flecha es bastante predecible. En funciones de flecha this siempre tomar谩 su valor del exterior. De hecho, la funci贸n de flecha ni siquiera tiene this.

    Si nos referimos a this en alg煤n lugar de la funci贸n de flecha, la b煤squeda se realiza exactamente de la misma manera que si fuera una variable regular, en el 谩mbito externo. Tambi茅n lo llamamos Alcance l茅xico.

    En nuestro ejemplo, this dentro de la funci贸n de flecha tiene el mismo valor que la this afuera, es decir, en el m茅todo double(). Entonces, this.items en la funci贸n de flecha es la misma que this.items en el m茅todo double() y es factory.items.

    Las funciones de flecha no se pueden llamar con el new operador

    Como la funci贸n de flecha no tiene this palabra clave, es obvio que no pueden admitir la new operador.

    Conclusi贸n

    Las funciones de flecha pueden ser confusas para empezar, pero es muy 煤til hacer que el c贸digo se comporte de manera m谩s predecible con el alcance l茅xico del this palabra clave. Tambi茅n es f谩cil para los dedos, ya que le permite escribir menos c贸digo.

    Como desarrollador de JavaScript, debe sentirse c贸modo us谩ndolo, ya que se usa ampliamente con diferentes marcos / bibliotecas frontend como React, Angular, etc. Espero que este tutorial pueda ayudarlo a decidir cu谩ndo y c贸mo implementar las funciones de flecha en su proyectos futuros.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *