Guia de tancaments de JavaScript

Introducci贸

Els tancaments s贸n un concepte una mica abstracte de el llenguatge JavaScript i es colen al costat de l’compilador de la programaci贸. No obstant aix貌, comprendre com JavaScript interpreta les funcions, les funcions niades, els 脿mbits i els entorns l猫xics 茅s imprescindible per aprofitar tot el seu potencial.

En aquest article, intentarem desmitificar aquests conceptes i proporcionar una guia senzilla per als tancaments de JavaScript.

Qu猫 茅s un tancament?

Primer, donem una ullada a la definici贸 oficial de MDN de tancament:

Un tancament 茅s la combinaci贸 d’una funci贸 agrupada (tancada) amb refer猫ncies al seu estat circumdant (l’entorn l猫xic). En altres paraules, un tancament li d贸na acc茅s a l’abast d’una funci贸 externa des d’una funci贸 interna.

En termes m茅s simples, un tancament 茅s una funci贸 que t茅 acc茅s a l’abast d’una funci贸 externa. Per entendre aix貌, donem una ullada a com funcionen els 脿mbits en JavaScript.

Abast en JavaScript

Abast determina quines variables s贸n visibles o poden ser referenciades en un context donat. L’abast es divideix 脿mpliament en dos tipus: Abast global i Abast local:

  • Abast global – variables definides fora d’una funci贸. Es pot accedir a les variables en aquest 脿mbit i modificar-les des de qualsevol lloc de el programa, d’aqu铆 el nom “global”.
  • Abast local – variables definides dins d’una funci贸. Aquestes variables s贸n espec铆fiques de la funci贸 en la qual es defineixen, de manera que es denominen “locals”.

Fem una ullada a una variable global i local en JavaScript:

let name = "Joe";function hello(){ let message = "Hello"; console.log(message + " " +name);}

En l’exemple anterior, l’abast de name 茅s global, 茅s a dir, es pot accedir des de qualsevol lloc. D’altra banda, message es defineix dins d’una funci贸, el seu abast 茅s local a l’hello() funci贸.

JavaScript utilitza l’脿mbit l猫xic quan es tracta d’脿mbits de funci贸. El que vol dir que l’abast d’una variable es defineix per la posici贸 de la seva definici贸 en el codi font. Aix貌 ens permet fer refer猫ncia a variables globals dins d’脿mbits m茅s petits. Una variable local pot utilitzar una variable global, per貌 viceversa no 茅s possible.

En

function outer(){ let x = 10; function inner() { let y = 20; console.log(x); } inner(); console.log(y)}outer();

Aquest codi d贸na com a resultat:

10error: Uncaught ReferenceError: y is not defined

els inner() funci贸 pot fer refer猫ncia x ja que est脿 definit al outer() funci贸. per貌, el console.log(y) declaraci贸 en el outer() la funci贸 no pot fer refer猫ncia a l ‘y variable perqu猫 est脿 definida en la inner() abast de la funci贸.

a m茅s, en aquest escenari:

let x = 10;function func1(){ console.log(x);}function func2() { let x = 20; func1();}func2();

La sortida ser脿:

10

Quan diem func1() des de dins func2(), tenim una variable d’脿mbit local x. No obstant aix貌, aquesta variable 茅s totalment irrellevant per func1() ja que no 茅s accessible en func1().

Aix铆, func1() comprova si hi ha una variable global amb aquest identificador disponible i el fa servir, el que d贸na com a resultat el valor de 10.

Tancaments sota el cap贸

Un tancament 茅s una funci贸 que t茅 acc茅s a les variables dels seus pares fins i tot despr茅s que la funci贸 externa hagi tornat. En altres paraules, un tancament t茅 tres 脿mbits:

  • Abast local: acc茅s a variables en el seu propi abast
  • Abast de la funci贸 principal: acc茅s a les variables dins del seu principal
  • Abast global: acc茅s a variables globals

Fem una ullada a un tancament a la feina, fent una funci贸 que retorni una altra funci贸:

function outer() { let x = 3 return function inner(y) { return x*y }}let multiplyByThree = outer();console.log(multiplyByThree(2));

Aix貌 resulta en:

6

Si fem un:

console.log(multiplyByThree);

Som rebuts amb:

function inner(y) { return x * y; }

Repassem el codi pas a pas per veure qu猫 est脿 passant sota el cap贸:

  • els outer() La funci贸 es defineix en l’脿mbit global.
  • outer() s’invoca i retorna una funci贸 que s’assigna a multiplyByThree.
  • es crea un nou context d’execuci贸 per outer().
    • Variable x est脿 configurat en 3.
  • Retorna una funci贸 anomenada inner().
  • La refer猫ncia a inner() est脿 assignat a multiplyByThree.
  • Quan la funci贸 externa finalitza l’execuci贸, s’eliminen totes les variables dins del seu abast.
  • Resultat de la crida a la funci贸 multiplyByThree(2) es registra a la consola.
  • inner() s’invoca amb 2 com a argument. Llavors, y s’estableix en 2.
  • Com inner() conserva la cadena d’abast de la seva funci贸 principal, en el moment de l’execuci贸 encara tindr脿 acc茅s a la valor de x.
  • Torna 6 que es registra a la consola.

en conclusi贸, fins i tot despr茅s de la exterior la funci贸 deixa d’existir, la interior la funci贸 t茅 acc茅s a les variables definides en l’abast de la exterior funci贸.

Visualitzaci贸 de tancaments

Els tancaments es poden visualitzar a trav茅s de la consola de l’desenvolupador:

function outer() { let x = 3 return function inner(y) { return x*y }}let multiplyByThree = outside();console.dir(multiplyByThree);

a l’executar el codi anterior a la consola de l’desenvolupador, podem veure que tenim acc茅s a l’context de inner(y). Despr茅s d’una inspecci贸 m茅s propera, podem veure que part del seu context 茅s un ] array, que cont茅 els tres 脿mbits dels que est脿vem parlant.

I vet aqu铆 , la matriu d’abastos cont茅 l’abast de la seva funci贸 principal, que cont茅 x = 3:

Casos d’煤s com煤

Els tancaments s贸n 煤tils perqu猫 ens ajuden a agrupar dades amb funcions que operen en aquestes dades. Aix貌 podria sonarles a alguns de vost猫s que estan familiaritzats amb la programaci贸 orientada a objectes (OOP). Com a resultat, podem usar tancaments en qualsevol lloc on puguem fer servir un objecte.

Un altre cas d’煤s important dels tancaments 茅s quan necessitem que les nostres variables siguin privades, ja que les variables definides en l’abast d’un tancament estan fora dels l铆mits de les funcions fora d’ell. A el mateix temps, els tancaments tenen acc茅s a variables en la seva cadena d’abast.

Vegem el seg眉ent exemple per entendre aix貌 millor:

const balance = (function() { let privateBalance = 0; return { increment: function(value){ privateBalance += value; return privateBalance; }, decrement: function(value){ privateBalance -= value; return privateBalance; }, show: function(){ return privateBalance; } }})()console.log(balance.show()); // 0console.log(balance.increment(500)); // 500console.log(balance.decrement(200)); // 300

En aquest exemple, hem definit una variable constant balance i configureu com el valor de retorn de la nostra funci贸 an貌nima. Adonar-se de privateBalance nom茅s es pot canviar cridant als m猫todes en balance.

Conclusi贸

Tot i que els tancaments s贸n un concepte bastant especialitzat en JavaScript, s贸n una eina important en un bon conjunt d’eines per a desenvolupadors de JavaScript. Es poden utilitzar per implementar amb eleg脿ncia solucions que d’una altra manera serien una tasca dif铆cil.

En aquest article, primer hem apr猫s una mica sobre els 脿mbits i com s’implementen en JavaScript. Despr茅s utilitzem aquest coneixement per comprendre com funcionen els tancaments sota el cap贸 i com usar-los.

Leave a Comment

L'adre莽a electr貌nica no es publicar脿. Els camps necessaris estan marcats amb *