Косвенный вызов функции в JavaScript - PullRequest
22 голосов
/ 02 марта 2011

Есть такие вещи, как

f.call(...)
f.apply(...)

Но тогда есть это

(1, alert)('Zomg what is this????!!!11')

«1», кажется, не имеет большого значения в этом контексте, следующее прекрасно работает:

(null, alert)('Zomg what is this????!!!11')
(1, null, alert)('Zomg what is this????!!!11')
(undefined, alert)('Zomg what is this????!!!11')

Не могли бы вы указать конкретную часть ECMAScript, которая описывает этот синтаксис?

Ответы [ 3 ]

45 голосов
/ 02 марта 2011

Вы просто используете Оператор запятой .

Этот оператор оценивает свои операнды только слева направо и возвращает значение из второго, например:

(0, 1); // 1
('foo', 'bar'); // 'bar'

В контексте вызова функции вычисление операнда просто получит значение, а не ссылку, это приводит к тому, что значение this внутри вызываемой функции указывает на глобальный объект (или оно будет * 1009). * в новом строгом режиме ECMAScript 5).

Например:

var foo = 'global.foo';

var obj = {
  foo: 'obj.foo',
  method: function () {
    return this.foo;
  }
};

obj.method();      // "obj.foo"
(1, obj.method)(); // "global.foo"

Как видите, первый вызов, который является прямым вызовом, значение this внутри method будет правильно относиться к obj (возвращающему "obj.foo"), второй вызов, оценка, выполненная оператор запятой заставит значение this указывать на глобальный объект (получая "global.foo").

Этот шаблон стал очень популярным в наши дни, чтобы делать косвенные вызовы eval, это может быть полезно в строгом режиме ES5, например, для получения ссылки на глобальный объект ( представьте, что вы находитесь в небраузерной среде, window недоступно):

(function () {
  "use strict";
  var global = (function () { return this || (1,eval)("this"); })();
})();

В приведенном выше коде внутренняя анонимная функция будет выполняться в кодовом блоке строгого режима, в результате чего значение this будет равно undefined.

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

Но лично в этом случае в строгом режиме я предпочитаю использовать конструктор Function для получения глобального объекта:

(function () {
  "use strict";
  var global = Function('return this')();
})();

Функции, созданные с помощью конструктора Function, являются строгими, только если они начинаются с директивы Use Strict, они не «наследуют» строгость текущего контекста, как это делают объявления функций или выражения функций.

8 голосов
/ 02 марта 2011

Это оператор запятой , который оценивает оба своих операнда и возвращает значение второго.

Итак, что-то вроде (null, alert) вычисляется для функции alert,который вы можете немедленно вызвать с помощью скобок.

Это описано в разделе 11.14 ECMA-262 (PDF).

3 голосов
/ 02 марта 2011

Оператор запятой заставляет выражения вычисляться последовательно.Заключение выражений в скобки возвращает значение последнего выражения.Так что (1, alert)("hello") функционально эквивалентно:

1;
alert("hello");

Вне головы, я не могу придумать причину сделать это.

...