Косвенный вызов функции в JavaScript
Есть такие вещи, как
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 ответа
Вы просто используете оператор запятой.
Этот оператор оценивает свои операнды только слева направо и возвращает значение из второго, например:
(0, 1); // 1
('foo', 'bar'); // 'bar'
В контексте вызова функции вычисление операнда просто получит значение, а не ссылку, это приводит к тому, что this
значение внутри вызываемой функции указывает на глобальный объект (или это будет undefined
в новом 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, они не "наследуют" строгость текущего контекста, как это делают объявления функций или выражения функций.
Это оператор запятой, который оценивает оба своих операнда и возвращает значение второго.
Итак, что-то вроде (null, alert)
оценивает до alert
Функция, которую вы можете сразу вызвать с помощью скобок.
Это описано в разделе 11.14 ECMA-262 (PDF).
Оператор запятой заставляет выражения вычисляться последовательно. Заключение выражений в скобки возвращает значение последнего выражения. Так (1, alert)("hello")
функционально эквивалентно:
1;
alert("hello");
Сверху головы я не могу придумать причину сделать это.