Funcions¶
Una funció és un bloc de codi que realitza una tasca determinada.
Les funcions ens permeten reutlitzar blocs de codi en diferents punts de l'execució dels nostres programes.
Una funció s'executa quan la invoquem amb l'operador ()
.
Sintaxi¶
Podem definir les nostres pròpies funcions en JavaScript seguint aquesta estructura:
function nom_funció( [ paràmetre1, paràmetre2, ... ] )
{
instruccions a executar;
[ return valor; ]
}
Una funció pot rebre paràmetres i retornar un valor de retorn.
Tant els paràmetres com el valor de retorn són opcionals.
Els paràmetres es reben dins dels parèntesis ()
en el moment d'invocar la funció.
Dins de la funció els paràmetres es comporten com variables locals.
Diferència entre paràmetres i arguments
Els paràmetres s'indiquen a la declaració d'una funció:
//a, b i c són paràmetres
function exemple( a, b, c ) { ... }
Els arguments es passen quan es crida una funció:
// Els valors 1, 2 i 3 són arguments
exemple( 1, 2, 3 );
Atenció
Si accedim a una funció sense els ()
se'ns retornarà la funció i no el resultat de la seva execució.
Nom de les funcions¶
Quan definim el nom de les funcions cal tenir en compte que:
- han de començar per una lletra
- opcionalment poden començar per
_
o$
- no poden ser paraules reservades del llenguatge
- distingeixen entre majúscules i minúscules
Valors de retorn¶
Idealment, una funció sempre hauria de retornar un valor.
Una funció que no contigui la sentència return
retornarà el valor undefined.
Quan el codi arriba a una instrucció return
dins d'una funció, l'execució de la funció s'atura immediatament.
function exemple(a, b) {
if ( a == 3 ) return b // Si a == 3 la funció retorna b i acaba
return a // Si a != 3 la funció retorna a i acaba
return 0 // Mai s'executarà aquesta instrucció
}
Variables dins de funcions¶
Les variables declarades dins d'una funció utilitzant var
o let
són locals de la funció.
// el codi que posem aquí NO pot utilitzar la variable "nom"
function exemple() {
var nom = "Joan";
// el codi que posem aquí POT utilitzar la variable "nom"
}
// el codi que posem aquí NO pot utilitzar la variable "nom"
Nombre d'arguments¶
Si invoquem una funció amb més arguments que paràmetres té declarats, els arguments sobrants són ignorats i no es produeix cap error.
function exemple( a, b ) { ... }
// El tercer argument no es té en compte
exemple( 10, 20, 30 );
Si invoquem una funció amb menys arguments dels paràmetres que té declarats, els que falten s'inicialitzen com a no definits (undefined):
function exemple( a, b, c ) { ... }
// El paràmetre 'c' rebrà el valor undefined
exemple( 10, 20 );
Valor per defecte dels paràmetres¶
Amb ES5 (ECMAScript 5) calia comprovar l'existència dels arguments dins del codi de la funció i inicialitzar-los a un valor per defecte si no en tenien:
function exemple( valor ) {
if ( valor === undefined) x = 10;
return valor * 2;
}
Des de la versió ES6 de JavaScript es poden definir valors per defecte pels paràmetres amb =
en el moment de declarar la funció.
function exemple( valor = 10 ) {
return valor * 2;
}
exemple(1) // Retornarà 2
exemple() // Retornarà 20
Ús en l'actualitat
Tots els navegadors moderns ja suporten ES6 i podem assignar valors per defecte directament amb =
Paràmetres per valor i per referència¶
Els paràmetres de tipus primitius (cadenes, numèrics i booleans) es passen sempre per valor, per tant es modifica el valor dels arguments passats a la funció.
Els paràmetres que siguin de tipus array o objecte es passen per referència.
Si es modifica algun dels seus elements dins de la funció, es modificarà també l'array o objecte original fora de la funció.
let x = [ 'valor_inicial' ];
function f( p ) {
p[0] = 'valor_nou';
}
f( x ); // x[0] = 'valor_nou'
Funcions anònimes¶
Són aquelles en les que ometem el nom de la funció.
Normalment s'utilitzen quan volem definir un bloc de codi que només s'ha d'executar en un punt concret del programa, i per tant no cal utilitzar un nom de funció ja que no la invocarem enlloc més.
Com a conseqüència no les podem invocar pel nom però sí que les podem:
- assignar com a argument d'una altra funció
setInterval( function() { ... }, 1000 );
- assignar a una variable o a un esdeveniment
element.onclick = function() { ... };
- executar immediatament (funcions autoinvocades)
(function (a) { return a + 10 })(10) // Retorna 20
Exemples
This¶
La paraula reservada this
fa referència a un objecte, que variarà segons diferents casos:
- Sol o dins d'una funció, fa referència a l'objecte global.
- Dins d'un mètode d'un objecte, fa referència al propi objecte.
- Dins d'un esdeveniment fa referència a l'element HTML que ha rebut l'esdeveniment.
Excepció
Si tenim activat el mode estricte, this
dins d'una funció retorna undefined enlloc de l'objecte global.
Nota
this no és una variable sinó una paraula reservada del llenguatge.
No podem canviar el valor de this.
Cal tenir clar quin és el context de this
en cada moment.
Per exemple, si assignem una funció directament a un esdeveniment onclick, dins de la funció this
farà referència a l'elemenent que ha rebut l'esdeveniment, per tant el que s'hagi clicat:
function pintaVermell() {
// Dins d'aquesta funció 'this' representa l'element HTML clicat
this.style.color = "white";
this.style.backgroundColor = "red";
}
// Assignem la funció directament a l'esdeveniment click de cada botó,
// sense posar () al final ja que provocaria l'execucio de la funció
document.getElementById("boto_1").onclick = pintaVermell;
document.getElementById("boto_2").onclick = pintaVermell;
document.getElementById("boto_3").onclick = pintaVermell(); // <-- ERROR!
En canvi, si enlloc d'assignar directament una funció a l'esdeveniment li assignem una funció anònima, tindrem la referència a this
dins del context de la funció anònima, però no més enllà. Si l'hem de passar a una altra funció ho podem fer com a argument:
function pintaColor(element, colorText, colorFons) {
// Dins d'aquesta funció 'this' representa l'objecte global (Window)
// i 'element' és un paràmetre que representa l'objecte que volem modificar
element.style.color = colorText;
element.style.backgroundColor = colorFons;
}
document.getElementById("boto_1").onclick = function() {
// Dins d'aquesta funció 'this' representa el botó clicat (HTML),
// i el podem passar com a paràmetre a una altra funció
pintaColor(this, "white", "red");
};
Expressions de funcions¶
Les expressions de funcions es declaren com un assignació de variable, però se'ls passa com a valor una funció:
let exemple = function ( a ) {
return a + 20;
}
exemple( 10 ); // Retorna 30
En aquest cas la variable exemple és de tipus funció, i conté el codi de la funció assignada:
typeof( exemple ); // Retorna 'function'
exemple.toString(); // Retorna 'function (a) { return a+20;}'
Les funcions es poden declarar en qualsevol punt del codi, però les podem invocar abans d'haver-les declarat gràcies al Hoisting.
En canvi les expressions de funcions no existeixen fins que l'execució del codi arriba a la línia on se les assigna a una variable.
Les expressions de funcions es poden reassignar, a diferència de les funcions que no es poden redeclarar en temps d'execució.
D'aquesta manera una mateixa crida a una expressió de funció pot estar invocant funcions diferents segons requereixi el nostre codi.
let suma10 = function (x) { return x + 10 }
let mult10 = function (x) { return x * 10 }
let f = suma10
f( 10 ); // Retorna 20
let f = mult10
f( 10 ); // Retorna 100
let f = suma10() // <-- ERROR, aquí no estem assignant la funció
// sinó el valor que retorna (NaN)
Funcions fletxa (arrow functions)¶
Són una notació alternativa i més compacta per declarar funcions.
Es comporten igual que les funcions declarades amb function
però cal tenir en compte que:
- no canvien el context de this al seu interior, sinó que mantenen el context del punt on s'ha invocat la funció fletxa
- no es poden utilitzar com a constructors
- sempre són anònimes
Sintaxi comparada amb les funcions anònimes tradicionals:
function ( a ) {
return a + 100;
}
S'elimina la paraula reservada function
i posem una fletxa (=>) entre ( ) i { }
( a ) => { return a + 100; }
Si la funció només té una línia i retorna un valor, no cal posar les claus { } i el return es fa implícitament
( a ) => a + 100;
Si hi ha un sol paràmetre, podem ometre els parèntesis
a => a + 100;
Funcions predefinides del llenguatge¶
Són funcions integrades per defecte en el llenguatge JavaScript i que podem fer servir quan les necessitem.
encodeURI()¶
Codifica una URI en format UTF-8 de manera que els caràcters especials que contingui es puguin transportar correctament, per exemple dins de capçaleres HTTP.
No codifica els següents caràcters: , / ? : @ & = + $ #
Si necessitem codificar tots els caràcters, podem fer-ho amb la variant encodeURIComponent
let text = encodeURI("Això està força bé");
decodeURI()¶
Fa la funció inversa de encodeURI()
i descodifica els caràcters especials d'una URI de manera que es pugui recuperar el text original.
Existeixen també les variants encodeURIComponent
/ decodeURIComponent
que converteixen un major conjunt de caràcters
let text = decodeURI("Aix%C3%B2%20est%C3%A0%20for%C3%A7a%20b%C3%A9");
eval()¶
Retorna el resultat d'avaluar una expressió o executar instruccions de JavaScript.
Si s'utilitza correctament pot ser molt potent però també és molt perillosa ja que permet la injecció de codi.
Atenció
Executar JavaScript a partir del contingut d'una cadena es considera un risc important, per tant es recomana evitar sempre l'ús de la funció eval().
isFinite()¶
Ens indica si un valor és un número vàlid.
isNaN()¶
Ens indica si el valor passat com a paràmetre no és un número.
Number()¶
Converteix el valor passat com a paràmetre en un valor numèric si és possible
String()¶
Converteix el valor passat com a paràmetre a una cadena.
parseInt()¶
Converteix el valor passat a un número enter, amb la particularitat que intenten fer la conversió fins a trobar el primer caràcter no numèric.
parseFloat()¶
Converteix el valor passat a un número amb coma flotant, amb la particularitat que intenten fer la conversió fins a trobar el primer caràcter no numèric.