Доступ переменной в ООП JS

144
12 января 2020, 22:00

В открытом методе init()

this._todoContainer = document.querySelector(this._settings.todoContainer);

сюда я из настроек записываю название контейнера в документе. Значение есть всё как бы нормально.

Далее я пользуюсь переменной в статическом методе

this._todoContainer // тоже делаю консоль лог и тут пусто

this._todoContainer.insertAdjacentHTML('beforeend', template);  

Так работает

document.querySelector('.dataTascksInfo').insertAdjacentHTML('beforeend', template);

Почему не доступна переменная this._todoContainer в другие методы?

Answer 1

TL;DR: В обычных методах, this указывает на экземпляр класса, а в статических - на сам класс (конструктор).

При обычном вызове, обращаться к свойствам экземпляра через this, можно только в нестатических методах.


Детально:

Начнем с того, что классы в JS - это синтаксический "сахар" для описания объектных типов. И чтобы разобраться в ситуации, придется пробежаться по теории. Для этого, возьмем простой пример:

class Box { 
  constructor() { this.contents = []; } 
  insert(something) { this.contents.push(something); } 
  static isEmpty()  { return this.contents.length === 0; } 
} 
 
const box = new Box();  
box.insert('cat');  
console.log(Box.isEmpty());   // ошибка


Как обрабатывается объявление "сахарного" класса:

Интерпретатор создает функцию Box() - конструктор объектов типа Box.

Далее, этой функции добавляется свойство1 prototype со значением в виде объекта, который будет наследоваться экземплярами. Прототип содержит методы "класса" - в данном случае, это только метод insert()2.

Статические методы становятся собственными методами функции-конструктора. В непосредственные свойства прототипа они не попадают.


Как работают вызовы методов:

Сначала выполняется поиск метода в объекте экземпляра, а затем в прототипах (по цепочке наследования "вверх", от ближайших предков к более дальним). Как только метод найден, поиск прекращается. Если не найден - выбрасывается исключение.

При вызове метода из прототипа, он временно "привязывается" к экземпляру, от имени которого вызван - и this внутри метода указывает на этот конкретный экземпляр3.

Вызов статических методов работает аналогично.
Но так как эти методы не в прототипе, и являются "собственностью" конструктора, вызываем мы от его имени - а значит, this внутри таких методов указывает на конструктор... у которого нет свойств экземпляров. Именно поэтому, в примере возникает ошибка при обращении из статического метода к свойству contents4.


1 Функции в JS являются объектами, и могут иметь свойства.

2 Прототип также содержит свойство constructor, которое является ссылкой на саму функцию-конструктор (Box.prototype.constructor === Box).

3 И не имеет значения, насколько "далеко" по цепочке наследования находится вызываемый метод. То есть, если бы мы в примере вызвали box.hasOwnProperty(...), метод из более дальнего предка Object - он тоже выполнился бы так, будто является собственным методом box.

4 Несмотря на то что это свойство создается конструктором - при использовании оператора new, this указывает на объект экземпляра еще до его возврата и присваивания переменнной box.

READ ALSO
HTML5 видео не работает loop когда много

HTML5 видео не работает loop когда много

Есть страница где идут 6 html5 видео подряд, у всех просписано loop="1"Каждое видео запускается когда находится в зоне видимости Но два последние...

147
Как узнать находится ли страница в закладках у пользователя

Как узнать находится ли страница в закладках у пользователя

Стоит задача, нужно поменять фон у элемента если пользователь добабил страницу в закладкиВопрос, как узнать из JS что страница добавлена в закладки,...

123
YEOMAN что это и для чего?

YEOMAN что это и для чего?

Что такое YEOMAN где это используется, и как начать с ним работать? Искал в интернете слишком сложно, можно объяснить для чайника :)

116