5
function foo() {
  return this;
}

let bar = {
  foo
};

console.log(
  foo(),

  bar.foo(),
  (bar.foo)(),

  (bar.foo = bar.foo)(), // здесь
);

Собственно, понятно, почему bar.foo() вернет bar. Почему (bar.foo)() вернет bar - тоже. А вот почему теряется контекст в последнем выражении - вообще непонятно.

Непонятно также, что делает такая конструкция. Что она в конечном итоге вызывает? Левый операнд или правый? (Понятно, что в данном конкретном случае разницы нет, но я говорю про общий случай).

smellyshovel
  • 5,224
  • @Grundy не содержится в "дубликате" ответа на мой вопрос. Ни на один из них. – smellyshovel Jan 26 '18 at 15:10

1 Answers1

4

foo() - вызов функции в глобальном контексте (тут все просто)

bar.foo() - вызов метода объекта bar - JS создал для вас ключи у объекта (вообще так создавать объекты не есть хорошо, но JS решил что это должно выглядеть так {foo: foo, baz: baz}). См. короткая нотация

(bar.foo)() - то же самое что и в прошлом случае

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

Дополнение

Если выполнить пример в строгом режиме - при потере контекста получим undefined. См this в контексте функции

tutankhamun
  • 11,366
  • 1
    Вот не знаю: слово "глобальную" может кого-то смутить и заставить думать, что такое происходит, только если функция объявлена вне объекта? – Regent Jan 10 '18 at 17:20
  • "не метод объекта, а глобальную функцию" - тогда что насчет предыдущего примера? – smellyshovel Jan 10 '18 at 17:21
  • @Regent исправлю, хотя нет - не исправлю. Функция без контекста вызывается в глобальном контексте – tutankhamun Jan 10 '18 at 17:22
  • Я правильно понимаю, что вся беда кроется в том, что оператор присваивания возвращает функцию (контекст которой, понятное дело, потерян)? Которая потом и вызывается (уже без контекста). – smellyshovel Jan 10 '18 at 17:23
  • @smellyshovel Да. Из правой части мы берем только функцию (контекста нет) ее значение помещаем в переменную, указанную в левой части присваивания, но результатом операции присваивания является как раз правая часть – tutankhamun Jan 10 '18 at 17:25
  • @tutankhamun в итоге в ответе можно оставить только то, что значение this - динамическое, поэтому теряется контекст при присвоении функции новой переменной и то, что вызывается правая часть. – smellyshovel Jan 10 '18 at 17:28
  • Но в целом спасибо, вроде понял, что к чему. – smellyshovel Jan 10 '18 at 17:29
  • Кстати, заметил, что предыдущая строка ((bar.foo)()) тоже возвращает window. С чем это может быть связано? Может быть как-нибудь со strict mode'ом? – smellyshovel Jan 10 '18 at 17:32
  • @smellyshovel тоже про него вспомнил :) – tutankhamun Jan 10 '18 at 17:33
  • @tutankhamun да, но тут одна маленькая загвоздочка возникает: почему 2 последних примера выдают window и undefined соответственно (в стрикт моде), а не undefined оба раза? – smellyshovel Jan 10 '18 at 17:35