Я ходил по чему-то странному, делая сегодня код JS.

Я хотел выполнить метод объекта, если свойство существует, и какую-то другую функцию, если его нет. Чувствуя себя немного причудливо, я написал что-то вроде:

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

(obj.method || some_other_function)();

Это выполняет obj.method, если он существует, и some_other_function в противном случае.

Но ключевое слово this ссылается на объект window при выполнении obj.method , и я абсолютно не знаю, почему.
Обратите внимание, что выполнение (obj.method)(); дает ожидаемый результат (это относится к моему объекту)

Очевидно, мне не нужен этот синтаксис для запуска моего кода, но мне действительно интересно, что здесь происходит.

Я не смог найти ответа ни здесь, ни где-либо еще, самое близкое, что я нашел, это этот интересный пост, но он не охватывает этот конкретный случай.

Кто-нибудь знает, что там происходит?

Вот скрипка, показывающая эту вещь в действии!

2
mikake 15 Дек 2015 в 22:44

3 ответа

Лучший ответ

(obj.method || some_other_function)();, по сути, такой же, как:

var f = obj.method || some_other_function;
f();

Вы удалили функцию из контекста obj, пропустив ее через или , прежде чем вызывать ее.

4
Quentin 15 Дек 2015 в 20:01

obj.method() является синтаксическим сахаром для

method.call(obj)

Также известен как вызов метода (отличается от вызова функции ). Если свойство (method) используется любым другим способом, оно возвращает значение функции. Например. используя его в бинарной операции, такой как

(obj.method || some_other_function)()

Делает его значением функции , а приведенное выше выражение является синтаксическим сахаром для

(obj.method || some_other_function).call(this)

this - это текущий контекст, а не obj.

(obj.method)() по-прежнему является вызовом метода, поскольку (expression) и expression рассматриваются как равные

0
Rune FS 16 Дек 2015 в 09:28

Ваша путаница очень распространена среди людей, изучающих JavaScript, и проистекает из неполного понимания this. Краткий ответ: ваш код выполняет obj.method() или some_other_function(). Контекст this внутри вызываемой функции относится к объекту, который вызвал эту функцию. В типичном случае использования вызова method функции (простой вызов obj.method()), obj вызывает method, и поэтому this ссылается на obj в функциональный блок.

Однако выражение (obj.method || some_other_function)() не вызывается никаким объектом, оно просто ... вызывается, верно? На самом деле происходит то, что это выражение вызывается из глобального пространства, которое в браузере является объектом window. Таким образом, вы можете думать о своем коде как о выполняющемся так:

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

window.(obj.method || some_other_function)();

И some_other_function, и obj.method вызываются из глобального пространства, потому что они оцениваются как выражение внутри вашего || условный блок. Это выражение на самом деле является просто свойством объекта window, и это то, что его вызывает. Сначала я тоже был смущен, очень интересная проблема, и спасибо Квентину за правильный ответ.

Вот отличное сообщение в блоге, которое помогает прояснить this в JavaScript: http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/

Отредактировано: я обновил этот пост, чтобы отразить правильный ответ, мой оригинальный ответ был неправильным.

0
Travis Neufeld 15 Дек 2015 в 23:01