Указатель this

Внутри метода доступен указатель this, ссылающийся на текущий контекст. С помощью этого указателя, используя точечную нотацию или квадратные скобки, можно получить доступ к свойствам текущего объекта внутри него:

<Переменная> = this.<Имя свойства>
this.<Имя свойства> = <Значение>
<Переменная> = this['<Имя свойства>']
this['<Имя свойства>'] = <Значение>

Пример обращения к свойству model внутри метода getModel():

let car = {
   model: 'ВАЗ-2109',
   getModel() {
      return this.model; // return this['model'];
   }
};

Если в данном примере указатель this удалить, то получим ошибку обращения к неопределенной локальной переменной:

ReferenceError: model is not defined

Для определения методов нельзя использовать стрелочные функции (лямбда-выражения), т. к. они не содержат собственного указателя this, а захватывают его из родительской области видимости. Поэтому они не могут иметь доступа к свойствам объекта:

let car = {
   model: 'ВАЗ-2109',
   getModel: () => {
      console.log(this);       // {}
      return this.model;
   }
};
console.log( car.getModel() ); // undefined

На самом деле при использовании функций указатель this также потерять очень просто. Достаточно присвоить ссылку на метод какой-либо переменной, а потом вызвать метод через переменную:

let car = {
   model: 'ВАЗ-2109',
   getModel() {
      return this.model;
   }
};
console.log( car.getModel() ); // ВАЗ-2109
let func = car.getModel;
// Потеряли this
console.log( func() );         // undefined

В этом случае следует передать контекст явным образом с помощью методов call(), apply() или bind() (см. разд. 10.5):

// OK
console.log( func.call(car) );  // ВАЗ-2109
console.log( func.apply(car) ); // ВАЗ-2109
let boundFunc = func.bind(car);
console.log( boundFunc() );     // ВАЗ-2109

Аналогичная ситуация возникает при передаче ссылки на метод в функции таймеров:

let car = {
   model: 'ВАЗ-2109',
   print() {
      console.log(this.model);
   }
};
setTimeout(car.print, 2000);                // undefined
setTimeout(car.print.bind(car), 2000);      // ВАЗ-2109

Потерять указатель this можно также внутри вложенной в метод функции:

let car = {
   model: 'ВАЗ-2109',
   func() {
      let print = function() {
         console.log(this.model);
      };
      print();
   }
};
car.func();           // undefined
car.func.call(car);   // undefined
car.func.apply(car);  // undefined

В этом случае методы call(), apply() и bind() нам не помогут. Существует несколько способов решения проблемы. Во-первых, можно передать указатель this в качестве параметра при вызове вложенной функции:

let car = {
   model: 'ВАЗ-2109',
   func() {
      let print = function(self) {
         console.log(self.model);
      };
      print(this);
   }
};
car.func();           // ВАЗ-2109

Во-вторых, можно воспользоваться замыканием, присвоив указатель this локальной переменной внутри метода:

let car = {
   model: 'ВАЗ-2109',
   func() {
      let self = this;
      let print = function() {
         console.log(self.model);
      };
      print();
   }
};
car.func();           // ВАЗ-2109

Учебник по Node.js и JavaScript
Учебник по JavaScript (Node.js) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов