Сначала посмотрим на такой пример:
var x = 0;
(function () {
var x = 1;
eval('alert(x)'); // 1
(1, eval)('alert(x)'); // 0
}());
∙ Для кода, выполненного через просто
eval(…)
, доступен скоп текущей функции, поэтому берется значение локальной переменной
x
.
∙ Для кода, выполненного через
(1, eval)(…)
, доступен только глобальный скоп, поэтому берется значение глобальной переменной
x
.
Чтобы понять, почему так происходит, рассмотрим обычный метод объекта:
var obj = {
method: function () {
return this;
}
};
var method = obj.method;
alert(obj.method() === obj) // true
alert(method() === window) // true
Как видим, когда вызываем метод через аксессор
obj.method
, то объектом активации функции становится сам
obj
и
this
является ссылкой на него.
А когда мы вызываем метод по прямой ссылке, то его объектом активации становится глобальный контекст, в случае браузерного JS – это
window
, и
this
в этом случае является ссылкой на
window
.
Вернемся к
eval
:
(1, eval)
Это обычное выражение, результатом которого является ссылка на функцию
eval
. Возвращается последнее значение после запятой. Но как можно заметить в обычном вызове
eval(…)
тоже нет объекта активации. Это особенность функции
eval
, объектом активации для нее является текущий скоп. Как оно там внутри реализовано мы не знаем, но можем представить происходящее следующим псевдокодом:
var x = 0;
function eval(code) {
with (this) {
return (function () {
return // результат выполнения code
}).call(this.context);
}
}
globalScope → {
x: 0,
eval: eval,
context: window
}
(function () {
var x = 1;
localScope → {
x: 1,
eval: eval,
context: window
}
localScope.eval('alert(x)'); // 1
globalScope.eval('alert(x)'); // 0
}());
Трюк
(1, eval)
отвязывает функцию
eval
от локального скопа. Не обязательно писать
(1, eval)
, можно как во втором примере получить ссылку на функцию:
var x = 0;
(function () {
var x = 1;
eval('alert(x)'); // 1
var globalEval = eval;
globalEval('alert(x)'); // 0
}());
Эффект будет такой же.
Соответственно в твоем примере
(1, eval)('this')
используется для получения глобального контекста.
Такую запись можно заменить на
new Function('return this')()
.