:sparkles: PWA :sparkles:
Twarz autora bloga

Piotr Kowalski

Organizator WarsawJS Trener YouTuber

bind() obok call() i apply() jako piękna natura języka

Zasada działania metody bind() opiera się na istniejących metodach call() i apply(), ale nie jest to nich podobna w jednym aspekcie (w sumie w najważniejszym).

Baner reklamujący artykuł

call() & apply()

Wyżej wymienione funkcje uruchamiają od razu funkcję na której są uruchomione.

Przykład poniżej:

var book = {
    title: "Pan Tadeusz"
};

var komputer = {
    title: "MacBook"
};

function getTitle(prefix) {
    return prefix + this.title;
}

console.log(getTitle.call(book, 'To jest: ')); // "To jest: Pan Tadeusz"
console.log(getTitle.call(komputer, 'To jest: ')); // "To jest: MacBook"

console.log(getTitle.apply(book, ['To jest: '])); // "To jest: Pan Tadeusz"
console.log(getTitle.apply(komputer, ['To jest: '])); // "To jest: MacBook"

Obie funkcje oczekują pierwszego parametru, którym będzie kontekst, czyli nowy świat jaki będzie dostępny, gdy w funkcji getTitle() będziemy chcieli pobrać coś z this-a.

Słowo kluczowe this wskazuje na kontekst w którym jest uruchomiony.

bind()

Funkcja z nagłówka zmienia używany kontekst w naszej funkcji. Ważne jest to, że jej nie uruchamia, tak jak robią to metody call() i apply(). Funkcja bind() zwraca tą samą funkcję, zmieniając jej świat oraz ewentualnie definiując wartości oczekiwanych parametrów.

Przykład użycia:

function printStatus() {
    console.log(this.isAvailable);
}

var contact = {
    isAvailable: true
};

printStatus(); // undefined

setTimeout(printStatus.bind(contact), 1000);

Po sekundzie w konsoli (DevTools) zobaczymy flagę (boolean) true.

Ale u mnie nie działa!

Podejrzewam, że używasz starej przeglądarki. Bardzo starej. Tutaj jest dostępna tablica ze wsparciem danego feature-a w przeglądarkach. Jak widzisz, cały rekord jest zielony. Oznacza to, że wszystkie przeglądarki wymienione w nagłówkach mają wsparcie do tej nowości z ES5.

W starszych przeglądarkach metoda bind() niestety nie istnieje, ale istnieje prosta implementacja przedstawiona poniżej. Wystarczy, że uruchomimy ten kod (zdefiniowany poniżej) i już nasz kod z bind() zadziała.

if (!Function.prototype.bind) {
    Function.prototype.bind = function (that) {
        var method = this;
        var slice = Array.prototype.slice;
        var args = slice.apply(arguments, [1]);

        return function () {
            return method.apply(that, args.concat(slice.apply(arguments, [0])));
        };
    };
}