Как скобки влияют на код в JavaScript? - PullRequest
3 голосов
/ 18 мая 2019

var obj, method;

obj = {
  go: function() { console.log(this); }
};

(method = obj.go)()

ПРИМЕЧАНИЕ: первый комментарий Федора к его ответу - это то, что мне помогло больше всего. Как следует из темы, это было больше о скобках, чем this.

В последней строке я понимаю, что круглые скобки заставят код внутри выполняться первым, поэтому method принимает значение свойства go, которое является функцией.

Затем () вызывает эту функцию, которая записывает window на консоль, потому что она не была вызвана как метод.

Если вместо (method = obj.go)() вы введете method = obj.go(), он сначала запустит функцию go, а method примет возвращенное ею значение. Поскольку go ничего не возвращает, это будет undefined. Значение, напечатанное go, будет obj.

Чего я не понимаю, так это почему, если я делаю (obj.go)(), напечатанное this будет obj, а не window?

Учитывая, как работает другой код, я ожидал, что этот код будет работать примерно так: obj.go вычисляется сначала в скобках, а затем функция запускается как IIFE (function() { console.log(this); })(). Так как функция не вызывается как метод obj, this по умолчанию имеет значение window.

1 Ответ

4 голосов
/ 18 мая 2019

(method = obj.go)() оценивается в два этапа.

  1. method = obj.go вычисляется и method var становится равным функции go объекта obj. Функции в JavaScript можно вызывать как методы или как функции, поэтому, в общем случае, не имеет значения, как вы определили функцию go.

  2. Тогда method() вызывается. Поскольку вы не указали значение для this (либо вызывая функцию method как метод какого-либо объекта, либо используя bind или call, оно вызывается с this, установленным в глобальный объект (в нестрогом режиме) или undefined (в строгом режиме)

При вызове obj.go() this устанавливается равным obj (аналогично использованию obj.go.call(obj) или method.call(obj)). Если вы вызываете просто method() this равно глобальному объекту (аналогично вызову obj.go.call(window))

EDIT

А чтобы получить obj как this с вашим примером, вы можете сделать так

(method = obj.go.bind(obj))()

Таким образом, вы не только назначаете функцию go переменной method, но и создаете привязку к конкретному this, равному obj

Хорошее чтение о вызове функции и это в JavaScript

...