Funkcje
08-03-2018 JS JSFunkcja
- Funkcja to blok kodu zaplanowany do wykonania konkretnego zadania, np. zsumowania dwóch liczb.
- Funkcja zostanie wykonana jeśli ją wywołamy.
- Funkcja może posiadać parametry.
- Funkcje są jednym z podstawowych ‘klocków’ JavaScriptu.
- Funkcja jest zbiorem wyrażeń, które wykonują jakieś zadanie, bądź obliczają wartość.
1. Deklarowanie
a) Function declaration (deklaracja funkcji)
Składa się ze słowa kluczowego function oraz:
- nazwy funkcji,
- listy argumentów zamkniętych w nawiasach i oddzielonych przecinkami,
- instrukcji JavaScript, które definiują funkcję, zamkniętą w nawiasach klamrowych, { }.
function square(number) {
return number * number;
};
Funkcja square przyjmuje jeden argument, nazwany number. Funkcja składa się z jednej instrukcji, która zwraca argument (number) pomnożony przez siebie. Instrukcja return oznacza wartość zwracaną przez funkcję.
- Return zawsze kończy działanie funkcji.
- Cokolwiek wrzucisz za returnem, nie zostanie wykonane.
- Funkcja nie musi posiadać return.
function sum (a, b) { | function sum (a, b) {
return a + b; | console.log('Hey!');
console.log('Hey!'); | return a + b;
}; | };
|
sum(2,1) // 3 | sum(2,1) // Hey! 3
b) function expression (wyrażenie funkcyjne):
Funkcję podstawiamy pod zmienną:
var sum = function(a, b) {
return a + b;
};
Preferujemy używanie function declaration, bo na dowolnej wysokości kodu możemy sięgać po taką funkcję.
Function declaration i function expression różnią się od siebie:
- sposobem zapisu,
- także tym, jak taki kod jest interpretowany przez przeglądarkę.
Funkcja zadeklarowana za pomocą deklaracji jest od razu dostępna dla całego skryptu. Możemy więc odwoływać się do funkcji, która jest zadeklarowana później w kodzie. Działa tutaj mechanizm hoistingu, znany ze zmiennych. Funkcje utworzone przez deklarację, poza naszymi plecami są przenoszone na początek kodu.
Przy wyrażeniu funkcyjnym mechanizm ten nie działa, a takie przedwczesne odwołanie się do funkcji jest niemożliwe. Funkcja zdefiniowana za pomocą wyrażenia musi być zadeklarowana przed jej wywołaniem.
#//Tutaj jest ok //Błąd
myFunction(); myFunction();
function myFunction() { const myFunction = function() {
console.log('...'); console.log('...');
}; };
2. Scope funkcji
Zakres widoczności zmiennych. Zmienne zadeklarowane w środku funkcji nie są widoczne poza funkcją, ale funkcja ma dostęp do zmiennych zadeklarowanych globalnie.
console.log(VAT); // ERROR: VAT is not defined
var factor= 1.9; // zmienna globalna
function getGross(nettoPrice) {
var VAT = 1.23;
console.log(VAT); // 1.23
console.log(factor); // 1.9
return nettoPrice* VAT;
}
3. Domknięcia- closures
Domknięcie to zasięg (obszar) tworzony przez funkcję, która ma dostęp do:
- swoich zmiennych
- zmiennych zadeklarowanych we funkcji, w której jest zagnieżdżona
- do zmiennych globalnych
- ma dostęp nie tylko do zmiennych funkcji nadrzędnej, ale również do jej parametrów
- poprzez domknięcie funkcja tworzy „swoje środowisko”
- zmiennych zdeklarowanych w ich zewnętrznym zasięgu
Domknięcia występują wtedy, gdy funkcja może zapamiętać i uzyskać dostęp do swojego zakresu leksykalnego, nawet po jej wywołaniu na zewnątrz tego zakresu.
Domknięcia to dostęp do zmiennej, która została stworzona wewnątrz zakresu innej funkcji i która zakończyła już swoje działanie.
Przykład 1
const add = function(a) {
let b = 20;
return function(c) {
return a + b + c;
}
};
Pójdźmy dalej:) Aby wywołać tę funkcję, iniciujemy zmienną, która wskazuje na add
.
const addTo30 = add(10);
console.log(addTo30); // ƒ (c) {return a + b + c;}
console.log(addTo30(50)); // 80
Wywołanie addTo30
w konsoli wyświetli funkcję:
ƒ (c) {
return a + b + c;
}
Dzięki clousers, ta funkcja przechowuje z zakresu wyższego (leksykalnego, nadrzędnego) wartości które będą potrzebne, czyli wartość 10.
Dlatego console.log(addTo30(50));
wyświetli wynik 80. Argument a
posiada wartość 20, argument b
wartość 10, zaś c
wartość 50. Dlatego wynik funkcji wynosi 80.
Przykład 2
function hello(name){
return function(day) {
console.log(`Cześć ${name}, jak tam ${day} u Ciebie?`)
}
};
const user = hello("Kasia");
console.log(user); //ƒ (day) {console.log(`Cześć ${name}, jak tam ${day} u Ciebie?`)}
console.log(user("środa")); // Cześć Kasia, jak tam środa u Ciebie?
Mamy zmienną user
, na której wywołujemy hello("Kasia")
. Dostajemy zwrotkę o funkcji z argumentem day
.
Wartość, która jest pod name
nie będzie w tej chwili potrzebna, ale interpreter zapamiętuje to.
Następnie wyświetlając user
z argumentem środa, parser wyświetla nam całą frazę, korzystając z tego co ma w pamięci, czyli z imienia ‘Kasia’.
3. Funkcja anonimowa
Pod zmienną podstawiliśmy funkcję, która nie ma własnej nazwy. Taka funkcja bez nazwy zwie się funkcją anonimową. Takie funkcje bardzo często stosuje się w przypadku pracy z eventami, gdzie nie występuje nawet użycie dodatkowej zmiennej:
document.querySelector('.element').addEventListener('click', function() {
...
});
4. Funkcje samowykonujące się w JS
Immediately-InvokedFunctionExpression (IIFE) (inaczej iffy)- czyli natychmiastowo wywoływane wyrażenie funkcyjne.
Mówiąc szczerze, IIFE nie jest niczym więcej niż funkcją (otoczoną wieloma nawiasami), która jest wykonywana natychmiast.
Czym różni się IIFE w porównaniu z funkcją, którą deklarujemy i natychmiast wywołujemy?
Główna różnicą jest to, że po uruchomieniu IIFE nie pozostawia żadnych śladów swojego istnienia. Wynika to głównie z tego, że wyrażenia IIFE są zwykle anonimowymi funkcjami, które nie mają nazw. Oznacza to, że nie możemy śledzić ich poprzez sprawdzanie zmiennych. Ponieważ kod umieszczany w IIFE znajduje się wewnątrz funkcji, wszystkie zadeklarowane zmienne są lokalne dla tej funkcji.
Jeśli wewnętrzny kod chcielibyśmy wykonać tylko jeden raz, to nie potrzebujemy nazwy funkcji. Po definicji funkcji chcielibyśmy od razu ją wywołać:
function() {...}(); #//zwróci błąd
Powyższy kod zwróci błąd. Gdy parser napotka powyższy zapis, potraktuje go jako deklarację, ponieważ deklaracja funkcji wymaga podania nazwy. Aby to naprawić powyższy zapis funkcji wystarczy objąć nawiasami:
(function() {...})();
I tak właśnie powstał nasz wzorzec samo wywołującej się funkcji anonimowej:
(function() {
console.log('Justyna'); //Justyna
})();
#// powyższy zapis jest równoznaczny z
function foo() {
console.log('Justyna');
}
foo(); //Justyna
Alternatywnym zapisem dla powyższego jest wzór zalecany przez jednego z guru JavaScript - Douglasa Crockforda.
(function() {...}());