• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Object Oriented JavaScript - pytanie

Object Storage Arubacloud
0 głosów
480 wizyt
pytanie zadane 17 listopada 2022 w JavaScript przez GniewoszPL Nowicjusz (160 p.)
edycja 17 listopada 2022 przez GniewoszPL

Hej.

Czy możecie wyjaśnić mi dlaczego na załączonym screenie this.menuElements działają bez problemu wewnątrz jednej funkcji w ramach klasy, ale już nie działają w ramach innej funkcji - umieszczonej w tej samej klasie?

 

class Tabs {
    constructor(selector) {
        this.menuElements = document.querySelectorAll(selector);

        if ( !this.menuElements ) {
            return;
        }

        this.menuElementsClick();
    }

    menuElementsClick() {
        for (var i = 0; i < this.menuElements.length; i++) {
            this.menuElements[i].addEventListener("click", this.change, false);
        }

        
    }

    change(e) {

        for (var i = 0; i < this.menuElements.length; i++) {
            this.menuElements[i].classList.remove('active');
            const id = this.menuElements[i].getAttribute('data-tab');
            document.getElementById(id).classList.remove('active');
        }


        e.target.classList.add('active');
        const id = e.currentTarget.getAttribute('data-tab');
        document.getElementById(id).classList.add('active');
    }
}

export default Tabs;



komentarz 17 listopada 2022 przez Comandeer Guru (602,400 p.)
Wstaw kod przy pomocy odpowiedniej funkcji edytora – będzie zdecydowanie łatwiej zauważyć, co się dzieje, niż na screenie.

3 odpowiedzi

+2 głosów
odpowiedź 17 listopada 2022 przez ScriptyChris Mędrzec (190,190 p.)

Domyślam się, że this jest gubiony wewnątrz metody changethis domyślnie jest ustawiane w momencie wywołania funkcji. Do event listenera przekazujesz this.change i w tym samym momencie kontekst jest gubiony, a już sam listener woła tą funkcję jako samo change (bez kontekstu, czyli domyślnie window lub undefined w zależności czy jest to strict mode).

W tym artykule jest to dobrze wytłumaczone https://javascript.info/reference-type

Możesz to naprawić poprzez:

  • przekazanie arrow function: (event) => this.change(event)
  • zbindowanie funkcji: this.change.bind(this)
+2 głosów
odpowiedź 17 listopada 2022 przez Comandeer Guru (602,400 p.)

Bo w chwili, gdy change() jest wywoływane jako event listener, to jego this jest zmienione (na element, na którym doszło do zdarzenia).

Są dwa rozwiązania:

  1. arrow function,
  2. Function.prototype.bind().

Arrow function pozwala na zachowanie kontekstu this, więc wystarczy otoczyć event listener w taką funkcję:

element.addEventListener( 'click', ( event ) => {
    this.change( event );
} );

Z kolei bind() pozwala stworzyć kopię danej funkcji, która ma na stałe przypisany konkretny kontekst, stąd też można to wykorzystać:

element.addEventListener( 'click', this.change.bind( this ) );

Pierwsze rozwiązanie jest IMO ciut ładniejsze + nie tworzymy dodatkowej kopii metody change().

komentarz 17 listopada 2022 przez GniewoszPL Nowicjusz (160 p.)
Hmm, czyli w pierwszym przypadku musiałbym wywoływać całą funkcję jako callback event listenera? Nie ma jakiegoś syntaxu, który pozwoliłby użyć change jako osobna metoda dla tej klasy, ale z arrow function?

Jeśli odpowiedź na powyższe brzmi - nie, to zostaje mi bind tylko, prawda?
0 głosów
odpowiedź 17 listopada 2022 przez GniewoszPL Nowicjusz (160 p.)
Dzięki Panowie - wszystko działa jak należy - tak jak pisaliście :)

Podobne pytania

0 głosów
2 odpowiedzi 1,115 wizyt
pytanie zadane 25 lipca 2015 w PHP przez Aurelian Spodarec Użytkownik (920 p.)
0 głosów
0 odpowiedzi 111 wizyt
pytanie zadane 11 grudnia 2018 w PHP przez s4bek Użytkownik (600 p.)
0 głosów
0 odpowiedzi 131 wizyt
pytanie zadane 5 grudnia 2018 w PHP przez s4bek Użytkownik (600 p.)

92,661 zapytań

141,556 odpowiedzi

319,998 komentarzy

62,028 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...