1

В связи со следующим кодом

function Popup (pop, name, html, handlers) {
    if (html) {
        $(document.body).append(html);
    }
    handlers = handlers || {};
    this.$pop = $(pop);
    this.selector = pop;
    this.name = name;
    this.$pop_wrapper = this.$pop.parent('.js__popup_main_wrapper');
Popup.instances[this.name] = this;
this.$pop.on('click', '.popup__close, .js__popup__close', this.hide.bind(this));

//Закрытие попапа при клике на маску и при нажатии Esc
if (this.$pop_wrapper) {
    this.$pop_wrapper.on('click', function(event) {
        var mask_wrapper = event.target;
        if (mask_wrapper.classList.contains('js__popup_main_wrapper')) {
            Popup.hideAll();
        }
    });
}

$(document).keyup(function(event) {
    if (event.keyCode === 27) {
        Popup.hideAll();
    }
});

this.$body = this.$pop.find('.popup__body_text');

this.onshow = handlers.show || null;
this.onhide= handlers.hide || null;

this.events = {
    closePopup: 'closePopup',
    openPopup: 'openPopup'
}

}

Popup.instances = {};

Popup.getInstance = function(name, pop, html, handlers) { if(Popup.instances[name]){ return Popup.instances[name]; }

if (pop){
    return new Popup(pop, name, html, handlers);
}
return null;

}; Popup.hideAll = function() { for (var popupName in Popup.instances) { if(Popup.instances.hasOwnProperty(popupName)){ Popup.instances[popupName].hide(); } } };

Popup.prototype.show = function() { Popup.hideAll();

//Скрываем скролл
$('body').css('overflow', 'hidden');
// временный костыль
// почему-то не всегда инициализируется dom-элемент попапа
if (!this.$pop.length) this.$pop = $(this.selector);
if (!this.$pop.length) return;

if (this.$pop_wrapper) {
    this.$pop_wrapper.css("display", "flex");
}

this.$pop
    .removeClass('hidden')
    .addClass('shown')
    .attr('data-opened', '');
this.onshow ? this.onshow() : null;

if (window.userCity && window.userCity.hideBlock) { //если открыт попап города(актуально для мобильной версии)
    //то закрыть блок выбора города
    window.userCity.hideBlock();
}

//создадим событие открытия попапа
eventEmitter.dispatch(this.events.openPopup, {
    popupName: this.name,
    popup: this.$pop
});

};

Popup.prototype.hide = function() { this.$pop .removeClass('shown') .addClass('hidden') .removeAttr('data-opened'); this.onhide ? this.onhide() : null;

if (this.$pop_wrapper) {
    this.$pop_wrapper.fadeOut(50);
}

var opened = $('[data-opened]').length;

if (opened === 0) {
    //Возвращаем скролл
    $('body').css('overflow', 'auto');
}

eventEmitter.dispatch(this.events.closePopup, {
    popupName: this.name,
    popup: this.$pop
});

};

Popup.prototype.setBodyText = function (text){ if(!text){ return; }

this.$body.html(text);

};

приведенном на Семантика свойства this.$pop был рассмотрен оператор

this.$pop.on('click', '.popup__close, .js__popup__close', this.hide.bind(this)).

Возник вопрос: "Правильно ли я понимаю, что в коде this.hide.bind(this))

  1. this перед hide указывает на попап окно,
  2. а this, который внутри bind указывает на иконку закрытия - '.popup__close, .js__popup__close'?"

1 Answers1

2
this.$pop.on('click', '.popup__close, .js__popup__close', this.hide.bind(this));

Нет, неправильно. Три this-а в этой строчке - это одно и то же.

  • а зачем его указывать дважды в таком случае? – ProgrammerOfParadoxThings Oct 23 '20 at 17:11
  • 2
    Чтобы при вызове hide, внутри hide был тот же this. Можно добиться того же иначе: () => this.hide() – vp_arth Oct 23 '20 at 17:12
  • @ProgrammerOfParadoxThings https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind –  Oct 23 '20 at 17:12
  • В () => this.hide() только есть нюанс, что его придётся переписывать вслед за методом, если у него изменится количество параметров. А bind() делает только привязку this и не трогает аргументы. –  Oct 23 '20 at 17:19
  • (...args) => this.hide(...args) =) Но тут я уже предпочёл бы bind) – vp_arth Oct 23 '20 at 17:20