Показать сообщение отдельно
  #2 (permalink)  
Старый 19.02.2016, 00:05
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Сначала посмотрим на такой пример:
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')().

Последний раз редактировалось Octane, 19.02.2016 в 09:01.
Ответить с цитированием