Przejdź do treści

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(). Funkcja bind() różni się od call() w jednym aspekcie — w sumie w najważniejszym!

Baner promują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 computer = {
    title: "MacBook"
};

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

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

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

Obie funkcje oczekują pierwszego argumentu, 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 uruchomienia funkcji, w której jest użyty.

bind()

Funkcja z nagłówka zmienia kontekst używany 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

var printContactStatus = printStatus.bind(contact);

printContactStatus(); // 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 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])));
        };
    };
}

Powyższy kod to tzw. polyfill — czyli rozwiązanie, które tworzy brakujące API.