Что делает конструкция (obj.f = obj.f)() и почему при ее использовании теряется контекст вызова?

205
11 января 2018, 23:56
function foo() {
  return this;
}
let bar = {
  foo
};
console.log(
  foo(),
  bar.foo(),
  (bar.foo)(),
  (bar.foo = bar.foo)(), // здесь
);

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

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

Answer 1

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

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

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

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

Дополнение

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

READ ALSO
Сравнение двух вложенных массива

Сравнение двух вложенных массива

Есть 2 вложенных массивава:

203
Задачи по Vue JS [требует правки]

Задачи по Vue JS [требует правки]

Начал изучение Vue JS, можете посоветовать какие-нибудь интересные задачки по Vue для наработки практики, желательно не супер сложные (тк

668
Вызов alert(alert(1))

Вызов alert(alert(1))

alert(alert(1)) - выводит undefined Не могу понять почему так выводит, потому что мыслю как то, что в алерте в скобках выведет 1 и соответственно получится...

219