#javascript #jquery #ajax #greasemonkey #eval
#javascript #jquery #ajax #greasemonkey #eval
Вопрос:
я пишу скрипт GreaseMonkey (используя jQuery), и мне нужны некоторые переменные, которые задаются скриптом на исходной странице, например, это:
<script type="text/javascript">
var rData = {"20982211":[1,0,1],"20981187":[8,0,4]};
</script>
Я извлекаю этот элемент с другой страницы и пытаюсь его оценить, но, как ни странно, это не работает:
$.get(link_url, null, function(data) {
alert("1:" rData);
eval($(data).find("script").text());
alert("2:" rData);
}
Странно то, что на консоли firebug это работает (я только что попробовал eval непосредственно на целевой странице без .get), хотя при запуске скрипта это не так. Он выдает мне «null» в обоих предупреждениях.
Есть идеи?
Комментарии:
1. Почему вы запускаете этот код через оператор eval, когда динамического кода нет? Если вы не ожидаете, что символ будет менять имена, просто ссылайтесь на символ. Если символ меняет имена, то как ваш код узнает, что его нужно искать?
Ответ №1:
ECMAScript 5 переопределен eval
так, что он не может добавлять привязки переменных к окружающей лексической среде.
http://whereswalden.com/2011/01/10/new-es5-strict-mode-support-new-vars-created-by-strict-mode-eval-code-are-local-to-that-code-only/ рассказывает о проблемах с eval
в ES 3.
Но в то же время eval слишком мощный. Поскольку встроенная сборка предназначена для C или C (по крайней мере, без информации, требуемой синтаксисом asm gcc), eval также подходит для JavaScript. В обоих случаях мощная конструкция препятствует многим оптимизациям. Даже если вы не заботитесь об оптимизации или производительности, способность eval вводить и удалять привязки значительно усложняет анализ кода, который ее использует.
…
способность eval добавлять привязки хуже. Это может сделать невозможным определение того, к чему относится имя, до выполнения:
var v;
function test(code)
{
eval(code);
return v;
}
Означает ли v в инструкции return глобальную переменную? Вы не можете знать, не зная кода, который eval будет скомпилирован и запущен. Если этот код равен «var v = 17;», он ссылается на новую переменную. Если этот код «/* psych! */» это относится к глобальной переменной. eval в функции деоптимизирует любое имя в этой функции, которое ссылается на переменную во внешней области видимости. (И не забывайте, что само имя test находится во внешней области видимости: если функция вернула test вместо v , вы не могли бы сказать, ссылается ли этот тест на окружающую функцию или на новую переменную, не зная кода.)
Одним из возможных решений вашей проблемы является использование другой конструкции вычисления, например, (new Function('alert(rData); ' ... '; alert(rData);'))
вводит полную лексическую среду.
Комментарии:
1. Итак… возможно ли затем разобрать правую часть присваивания и присвоить ее переменной каким-либо другим способом?
2. @Fabian Zeindl, предполагая, что вы доверяете исходному коду и знаете, какое имя переменной он создает, вы можете сделать
(new Function(jsFromScript "; return rData;")())
.3. @Mike Это только в
strict
режиме, чего здесь нет.4. @Sean, я перечитал 10.4.2. Я думаю, ты прав. Неясно, находится ли приведенный выше фрагмент кода в строгой среде.
5. @Mike, на самом деле это совсем не непонятно — я сомневаюсь, что там есть
"use strict;
утверждение.. Кроме того, это не применимо в любом случае, посколькуeval
не помешало бы установке переменной.