Ответ 1
Вы используете Оператор Comma.
Этот оператор только оценивает свои операнды слева направо и возвращает значение из второго, например:
(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
, строгие, только если они начинаются с Использовать Strict Directive, они не "наследуют" строгость текущего контекста, как объявления функций или выражения функций.