Самописный ООП-слайдер на javascript — почему ошибка (замыкания)?

Пытаюсь делать свой слайдер в ооп-стиле. Вот код:
spoiler
var prevBtn = document.querySelector('.btn-prev--js');
var nextBtn = document.querySelector('.btn-next--js');

  var sliderImgs = document.querySelectorAll('.slider-img');
  var i = 0;

function Slider(images, prevBtn, nextBtn) {
      this.images = images;
      this.i = 0;

      prevBtn.onclick = function () {
          hide(this.images[this.i], 19);
          this.i--;

          if (this.i < 0) {
              this.i = this.images.length - 1;
          }

          show(this.images[this.i], 19);
      };

      nextBtn.onclick = function () {
          hide(this.images[this.i], 19);
          this.i++;

          if (this.i > this.images.length - 1) {
              this.i = 0;
          }

          show(sliderImgs[this.i], 19);
      }
  }

  var mySlider = new Slider(sliderImgs, prevBtn, nextBtn);


Я хочу сделать так, чтобы можно было указывать в конструкторе собственные кнопки управления. И в теле функции я написал .onclick, но, боюсь, в этом и кроется ошибка. Что-то с замыканиями? Вот ошибка:
common.js:47 Uncaught TypeError: Cannot read property 'undefined' of undefined
    at HTMLButtonElement.Slider.nextBtn.onclick (common.js:47)
  • Вопрос задан
  • 1073 просмотра
Решения вопроса 2
@kttotto
пофиг на чем писать
function Slider(images, prevBtn, nextBtn) {
      var self = this;
      this.images = images;
      this.i = 0;

      prevBtn.onclick = function () {
          hide(self.images[self.i], 19);
          self.i--;

          if (self.i < 0) {
              self.i = self.images.length - 1;
          }

          show(self.images[self.i], 19);
      };

      nextBtn.onclick = function () {
          hide(self.images[self.i], 19);
          self.i++;

          if (self.i > self.images.length - 1) {
              self.i = 0;
          }

          show(sliderImgs[self.i], 19);
      }
  }
Ответ написан
Stalker_RED
@Stalker_RED
Если прописать в обработчике console.log(this), то вы увидите, что там не ваш слайдер, а кнопка по которой кликнули.

Можно переписать так:
function Slider(images, prevBtn, nextBtn) {
      this.images = images;
      var self = this;
      // ...
      prevBtn.onclick = function () {
          hide(self.images[self.i], 19);
          self.i--;
          // ...
      };
  }


Другой вариант, использовать в качестве обработчика стрелочную функцию. Эти функции захватывают контекст в котором были объявлены, а не тот, где были вызваны.
// ...
  nextBtn.onclick = () => {
    console.log(this.images)
  };
// ...
https://jsfiddle.net/06v3j7f3/

И вообще, лучше избегать onclick. Я понимаю, что в первых главах большинства учебников его упоминают, так как по сравнению с addEventListener он кажется милым и пушистым, но вообще это неудобный привет из девяностых, имхо. Достаточно того факта, что вы не можете сделать два разных onclick'а на одной кнопке.

Подкину вам еще пищу для размышлений: что будет, если на странице будет ДВА ваших слайдера? Или больше.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы