ErichAltheim
@ErichAltheim
Программист

Как интерпретировать this в данном примере?

function CoffeeMachine(power) {
  this.waterAmount = 0;

  var WATER_HEAT_CAPACITY = 4200;

  var self = this; // Вопрос по этой строке

  function getBoilTime() {
      return self.waterAmount * WATER_HEAT_CAPACITY * 80 / power;
    }

  function onReady() {
    alert( 'Кофе готово!' );
  }

  this.run = function() {
    setTimeout(onReady, getBoilTime());
  };

}

var coffeeMachine = new CoffeeMachine(100000);
coffeeMachine.waterAmount = 200;

coffeeMachine.run();


Выше код, взятый с сайта learn.javascript.ru - меня конкретно интересует конструкция var self = this; помогите разобраться, насколько я знаю this это ссылка на текущий объект после создания объекта но данная конструкция не работает при конкретном присвоении объекта. Я не могу понять эту строку хотя с this разобрался. Из данной ситуации сам вышел путем создания промежуточной переменной var water = 0; this.waterAmount = water; тогда все без этих спорных конструкций все прекрасно работает
  • Вопрос задан
  • 386 просмотров
Решения вопроса 3
AlekseyNemiro
@AlekseyNemiro
full-stack developer
function CoffeeMachine(power) {
  //...

  var self = this; // запоминаем ссылку на текущий объект

  //...

  function getBoilTime() {
    // здесь this будет ссылкой на window, 
    // т.к. вызов метода getBoilTime() происходит из другого контекста
    // доступ к исходному объекту возможен через ссылку, 
    // которая была передана в переменную self
    console.log('this', this);
    console.log('self', self);
    return self.waterAmount * WATER_HEAT_CAPACITY * 80 / power;
  }

  // ...

  this.run = function() {
    setTimeout(onReady, getBoilTime());
  };
}


Привязка контекста и карринг: "bind"

С передачей контекста код будет примерно таким:

function CoffeeMachine(power) {
  this.waterAmount = 0;

  var WATER_HEAT_CAPACITY = 4200;

  function getBoilTime() {
      console.log('getBoilTime', this);
      return this.waterAmount * WATER_HEAT_CAPACITY * 80 / power;
    }

  function onReady() {
    alert( 'Кофе готово!' );
  }

  this.run = function() {
    console.log('run', this);
    var interval = getBoilTime.apply(this, null);
    setTimeout(onReady, interval);
  };

}

var coffeeMachine = new CoffeeMachine(100000);
coffeeMachine.waterAmount = 200;

coffeeMachine.run.apply(coffeeMachine, null);
Ответ написан
@zolotykh
web-разработчик
Когда вам необходимо обратиться к конкретному контексту из другого объекта, то используя ключевое слово this вы обратитесь к контексту текущего объекта из которого происходит обращение, именно поэтому создается альтернативная ссылка на необходимый контекст.
Ответ написан
evgeniy8705
@evgeniy8705
Повелитель вселенной
При передачи функции в setTimeout, контекст будет потерян,и теперь this будет равен не новому объекту, а будет равен undefined.
Поэтому если не использовать какой нибудь метод сохранения контекста, работать ничего не будет.
Например если в функции не использовать метод с сохранением контекста в переменную в замыкании, а просто писать this.метод то будет ошибка.
function getBoilTime() {
  return this.waterAmount * WATER_HEAT_CAPACITY * 80 / power;
}


В данном случае, this будет не новый объект, а будет равен undefined.
поэтому вызов undefined.метод приведет к ошибке.
Для решения данной проблемы используют неявный вызов с call/apply, сохранение контекста в новую переменную как в этом случае, или функцию bind, которая позволяет сохранить контекст для функции.

Ссылки:
Потеря контекста
Привязка контекста при помощи bind
call/apply
Сохранение контекста (habrahabr)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
18 апр. 2024, в 21:56
2000 руб./за проект
18 апр. 2024, в 21:00
150 руб./за проект