Funkcja w programowaniu to blok kodu zaprojektowany do wykonania określonego zadania. Jest to jedno z podstawowych narzędzi, które pozwala na wielokrotne używanie tego samego kodu, co zwiększa modularność i czytelność aplikacji.

Definiowanie funkcji

1. Deklaracja funkcji (Function Declaration):

function pow(x, y) {
    return Math.pow(x, y);
}
console.log(pow(2, 3)); // Wynik: 8

Charakterystyka: Funkcje zdefiniowane w ten sposób są „hoistowane”, co oznacza, że mogą być wywołane nawet przed ich zadeklarowaniem w kodzie.

Zastosowanie: Deklaracja funkcji jest idealna w sytuacjach, gdzie dostępność funkcji na poziomie globalnym lub w całym zakresie kodu jest pożądana, niezależnie od miejsca jej deklaracji w skrypcie.

2. Wyrażenie funkcyjne (Function Expression):

const pow = function(x, y) {
    return Math.pow(x, y);
};
console.log(pow(2, 3)); // Wynik: 8

Charakterystyka: W przeciwieństwie do deklaracji funkcji, wyrażenia funkcyjne nie są hoistowane, co oznacza, że nie można ich wywołać przed ich zadeklarowaniem. Funkcje te mogą być anonimowe (jak w podanym przykładzie) lub nazwane, co wpływa na to, jak są one prezentowane w stosie wywołań.

Zastosowanie: Wyrażenia funkcyjne są szczególnie przydatne, gdy funkcja ma być przekazywana jako argument callbackowy lub gdy jej definicja powinna pozostać ukryta przed globalnym zakresem.

3. Funkcja strzałkowa (Arrow Function)

Wprowadzone w ECMAScript 6, funkcje strzałkowe oferują zwięzłą składnię i mają kilka unikalnych cech ułatwiających pracę z funkcjami w JavaScript.

Funkcja strzałkowa z jednym parametrem

const square = x => x * x;
console.log(square(5)); // Wynik: 25

Charakterystyka: Gdy funkcja strzałkowa przyjmuje tylko jeden argument, nawiasy () są opcjonalne. Znak => umieszczony bezpośrednio przed wyrażeniem x * x automatycznie zwraca wynik tego wyrażenia. Brak jest tu słowa kluczowego return, co jest typowe dla jednolinijkowych funkcji strzałkowych, które wykonują jedno konkretne wyrażenie

Funkcja strzałkowa z nawiasami {} i wymaganym return

const add = (a, b) => {
    const result = a + b;
    return result;
};
console.log(add(5, 3)); // Wynik: 8

Charakterystyka: Użycie nawiasów () wokół parametrów jest wymagane, gdy funkcja przyjmuje więcej niż jeden argument. W ciele funkcji znajduje się więcej niż jedno wyrażenie, więc wymagane jest jawnie zwrócenie wyniku przy pomocy słowa kluczowego return.

Funkcja strzałkowa bez parametrów

const printHello = () => console.log("Hello");
printHello(); // Wyświetla: "Hello"

Charakterystyka: Nawiasy () są obowiązkowe, gdy funkcja nie przyjmuje żadnych argumentów. Funkcja ta bezpośrednio wykonuje działanie, takie jak wypisanie tekstu, i nie zwraca wartości. Dzięki jednolinijkowej formie, return jest niepotrzebny.

Specjalna cecha funkcji strzałkowych:

Funkcje strzałkowe nie tworzą własnego kontekstu this. Oznacza to, że this jest dziedziczone z otaczającego zakresu kodu, co jest kluczowe w przypadkach, gdy funkcja jest używana jako callback i musi odwołać się do this zewnętrznego kontekstu.

Zastosowanie:

Funkcje strzałkowe są szczególnie użyteczne w operacjach na tablicach, takich jak map, filter, reduce, oraz w każdym przypadku, gdy potrzebne jest utrzymanie kontekstu this bez automatycznego wiązania go do nowego obiektu.

4. IIFE (Immediately Invoked Function Expression):

(function() {
    console.log("Hello, world!");
})();

Definicja: IIFE to wyrażenie funkcyjne, które jest natychmiast wywoływane po jego zdefiniowaniu.

Zastosowanie: IIFE jest szczególnie przydatne w starszych wersjach JavaScript, które nie obsługują zmiennych blokowych takich jak let czy const. Umożliwia tworzenie nowego zakresu, izolując zmienne i logikę od globalnego zakresu, co pomaga unikać konfliktów i zanieczyszczenia globalnego środowiska.

5. Funkcje anonimowe

Funkcje anonimowe to funkcje bez jawnie przypisanej nazwy, użyteczne w wielu kontekstach programistycznych.

Zastosowanie:

Jako callback w metodach tablicy:

const numbers = [1, 2, 3];
const doubled = numbers.map(function(num) {
    return num * 2;
});
console.log(doubled); // Wynik: [2, 4, 6]

Tutaj funkcja przekazana do map jest anonimowa, służy tylko do zdefiniowania operacji przekształcenia elementów tablicy.

W operacjach asynchronicznych:

setTimeout(function() {
    console.log("Hello after 3 seconds");
}, 3000);

W powyższym przykładzie, funkcja przekazana do setTimeout jest anonimowa i wywoła się po upływie określonego czasu.

W IIFE (Immediately Invoked Function Expression):

(function() {
    console.log("Executed immediately");
})();

W tym przypadku, anonimowa funkcja jest wywołana natychmiast po zdefiniowaniu. Jest to częsty sposób na izolowanie zmiennej lub logiki w swoim zakresie.

W programowaniu zdarzeniowym:

document.getElementById('my-button').addEventListener('click', function() {
    alert('Button clicked!');
});

Funkcja obsługi zdarzenia kliknięcia jest anonimowa i służy jedynie do reakcji na kliknięcie przycisku.

Zwracanie wartości przez funkcje

W JavaScript, funkcje bez słowa kluczowego return domyślnie zwracają undefined.

function sayHello(name) {
    console.log(`Hello, ${name}!`);
}

const greeting = sayHello("Alice");
console.log(greeting); // undefined

Funkcja sayHello wyświetla wiadomość, ale nie zwraca wartości, więc zmienna greeting otrzymuje undefined.

Jak działa hoisting z funkcjami?

Deklaracje funkcji

console.log(greet("Alice")); // Wywołanie funkcji przed jej zadeklarowaniem

function greet(name) {
    return `Hello, ${name}!`;
}

W przypadku deklaracji funkcji, JavaScript „przenosi” całą definicję funkcji na górę zakresu. Dzięki temu można wywołać funkcję greet przed jej zadeklarowaniem w kodzie.

Wyrażenie funkcyjne

console.log(greet("Alice")); // TypeError: greet is not a function

const greet = function(name) {
    return `Hello, ${name}!`;
};

W przypadku wyrażeń funkcyjnych, tylko deklaracja zmiennej (const greet) jest hoistowana na górę zakresu jako undefined. Definicja funkcji nie jest dostępna, dopóki wykonanie kodu nie dotrze do linii, w której funkcja jest faktycznie zdefiniowana. Dlatego próba wywołania greet przed przypisaniem do niej funkcji skutkuje błędem TypeError.

Nazwa funkcji dostępna w stack trace

function calculateArea(width, height) {
    if (typeof width !== 'number' || typeof height !== 'number') {
        throw new TypeError("Both width and height must be numbers.");
    }
    return width * height;
}

function triggerError() {
    return calculateArea("width", 10);  // Celowo błędne wywołanie dla demonstracji
}

try {
    triggerError();
} catch (error) {
    console.error(error.stack);
}

//// Stos wywołań pokaże `calculateArea` i `triggerError`

Nazwy funkcji calculateArea i triggerError są widoczne w stack trace, co ułatwia debugowanie. W przypadku błędów, JavaScript dostarcza dokładne informacje o miejscu, w którym wystąpił błąd, włącznie z nazwami funkcji i liniami, co pozwala szybko zidentyfikować i rozwiązać problem.

//VM749:15 TypeError: Both width and height must be numbers.
//at calculateArea (<anonymous>:3:15)
//at triggerError (<anonymous>:9:12)
//at <anonymous>:13:5

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *