Обработка двойных ()
var global = (function () { return this || (1, eval)('this'); }()); Подскажите как обрабатывается код такого вида. (1, eval)('this') |
Сначала посмотрим на такой пример:
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')() . |
Часовой пояс GMT +3, время: 06:59. |