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:
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.