@civaru

Почему ссылка замыкается на последний элемент экземпляра?

Не могу понять какой-то фундаментальной вещи JavaScript, то-ли замыкание, то-ли наследование. Есть код небольшого "класса". Рабочий пример https://jsfiddle.net/1ds0s3k9/.

Далее сам код:

function extend( a, b ) {
    for( var key in b ) {
        if( b.hasOwnProperty( key ) ) {
            a[key] = b[key];
        }
    }
    return a;
}

function Notification( options ) {
    this.options = extend( {}, this.options );
    extend( this.options, options );
    this._init();
}

Notification.prototype.options = {
    wrapper : document.body,
    message : 'yo!',
    type : 'error',
    elements : {}
};

Notification.prototype._init = function() {
    var $this = this;
    this.html = document.createElement( 'div' );
    this.html.innerHTML = '<div class="ns-box-inner">' + this.options.message + '\
                           <div><a class="ns-box-link" href="javascript://">some link</a></div>\
                           </div>';

    this.options.elements.link = this.html.querySelector('.ns-box-link');

    this.options.elements.link.addEventListener('click', function() {
        console.log($this.options.elements.link);
        console.log($this);
    });

    this.options.wrapper.append(this.html);
}

Создаем пару экземпляров

var ntfc1 = new Notification({
    message: '<p>This is just a simple notice. Everything is in order and this is a <a href="#">simple link</a>.</p>',
    type: 'notice'
});

var ntfc2 = new Notification({
    message: 'Hello world',
    type: 'error'
});

Проблема возникает в следующем месте кода:

this.options.elements.link = this.html.querySelector('.ns-box-link');

this.options.elements.link.addEventListener('click', function() {
        console.log($this.options.elements.link);
        console.log($this);
});

Почему при клике вывод console.log($this); выводит правильную ссылку на каждый экземпляр, а вывод console.log($this.options.elements.link); ссылается на элемент который находится в последнем экземпляре класса?

Видео для наглядности https://youtu.be/kMUYs80tn7Y.
  • Вопрос задан
  • 89 просмотров
Решения вопроса 1
rockon404
@rockon404
Frontend Developer
Потому что у вас свойство elements в прототипе. Все экземпляры используют один и тот же объект elements. В итоге сколько экземпляров вы не создадите, во всех будет один и тот же объект this.opions.elements со свойством link переопределенным в конструкторе последнего экземпляра.
Поосторожней с прототипами. В прототипы помимо функций выносят только статику, но никак не динамические значения, разве, что счетчики, но это очень узко применимый и редкий кейс.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы