Метод может быть извлечен из объекта в отдельную переменную (например const TEST = myObject.myMethod). Когда метод TEST() вызывается отделенным от исходного объекта, можно предположить, что this - это объект myObject, для которого был определен метод.

Однако, если метод вызывается отделенным от объекта (т.е. как TEST()), то происходит вызов функции, где this - это глобальный объект window или undefined в строгом режиме (см. 2.1 и 2.2).

var myObject = {
  myMethod: function(){
    console.log(this)
  }
}
const TEST = myObject.myMethod;

myObject.myMethod()  // => myObject
TEST()  // => window

Только связанная функция myObject.myMethod.bind(myObject) (использование .bind() см. в главе 6) исправляет контекст, привязывая this к объекту, которому принадлежит метод.

В следующем примере определяется конструктор Pet и создается его экземпляр - myDog. Затем setTimout() через 1 секунду отобразит информацию об объекте myDog:

function Pet(type, legs) {
  this.type = type;
  this.legs = legs;
  this.info = function() {
    console.log(this === myDog);  // => false
    console.log('Животное -', this.type);
    console.log('Количество лап -', this.legs);
  }
}
const myDog = new Pet('Собака', 4);

myDog.info();  // => Животное - Собака | Количество лап - 4
setTimeout(myDog.info, 1000);  // => Животное - undefined | Количество лап - undefined

На первый взгляд кажется, что setTimeout(myDog.info, 1000) вызовет myDog.info(), который покажет информацию об объекте myDog.

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

setTimout(myDog.info);
// эквивалентны
const extractedInfo = myDog.info;
setTimout(extractedInfo);

Когда отделенный метод info вызывается как функция, this становится глобальным объектом (или undefined), но не объектом myDog. Таким образом, информация об объекте не отображается корректно.

Функция связывается с объектом с помощью метода .bind() (см. главу 6). Если отделенный метод связать с объектом myDog, проблема отображения контекста будет решена:

function Pet(type, legs) {
  this.type = type;
  this.legs = legs;
  this.info = function() {
    console.log(this === myDog);  // => true
    console.log('Животное -', this.type);
    console.log('Количество лап -', this.legs);
  }
}
const myDog = new Pet('Собака', 4);

// Создадим связанную функцию
const boundInfo = myDog.info.bind(myDog);
setTimeout(boundInfo, 1000);  // => Животное - Собака | Количество лап - 4

myDog.info.bind(myDog) возвращает новую функцию, которая выполняется точно так же, как info, но с this как у myDog даже при вызове функции.

Альтернативное решение - определить метод info() как стрелочную функцию, которая связывает this лексически:

function Pet(type, legs) {
  this.type = type;
  this.legs = legs;
  this.info = () => {
    console.log(this === myDog);  // => true
    console.log('Животное -', this.type);
    console.log('Количество лап -', this.legs);
  }
}
const myDog = new Pet('Собака', 4);

setTimeout(myDog.info, 1000);  // => Животное - Собака | Количество лап - 4

Если вы хотите использовать классы и связать this с экземпляром класса в своем методе, используйте стрелочную функцию как свойство класса:

class Pet {
  constructor(type, legs) {
    this.type = type;
    this.legs = legs;
  }
  info = () => {
    console.log(this === myDog);  // => true
    console.log('Животное -', this.type);
    console.log('Количество лап -', this.legs);
  }
}
const myDog = new Pet('Собака', 4);

setTimeout(myDog.info, 1000);  // => Животное - Собака | Количество лап - 4