Introducción
Contenido
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:
Te puede interesar:Envío de solicitudes AJAX en Vue.jsfunction 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:
Te puede interesar:Eliminar elemento de una matriz en JavaScriptWindow {...}
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:
Te puede interesar:Cómo usar module.exports en Node.jsHello 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.