Установить переменную внутри Eval (JavaScript) - PullRequest
2 голосов
/ 05 мая 2011

Я пишу сценарий 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), когда я запускаю скрипт, хотя это не так. Это дает мне «ноль» в обоих оповещениях.

Есть идеи?

1 Ответ

4 голосов
/ 05 мая 2011

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 ++ (по крайней мере, без синтаксиса информации, необходимого gcc для asm), она также подходит для JavaScript. В обоих случаях мощная конструкция подавляет многие оптимизации. Даже если вы не заботитесь об оптимизации или производительности, способность eval вводить и удалять привязки делает код, который использует его, гораздо сложнее для размышления.

...

Способность eval добавлять привязки хуже. Это может сделать невозможным сказать, на что ссылается имя до времени выполнения:

var v;
function test(code)
{
  eval(code);
  return v;
}

Означает ли v в выражении return глобальную переменную? Вы не можете знать, не зная, что код eval будет компилироваться и выполняться. Если этот код "var v = 17;" это относится к новой переменной. Если этот код "/ * psych! * /", Это относится к глобальной переменной. Функция eval в функции деоптимизирует любое имя в этой функции, которое ссылается на переменную в пределах области действия. (И не забывайте, что сам тест имени находится во вложенной области: если функция вернула test вместо v, вы не могли бы сказать, ссылался ли этот тест на включающую функцию или на новую переменную, не зная кода.)

Одним из возможных решений вашей проблемы является использование другой конструкции оценки, например, (new Function('alert(rData); ' + ... + '; alert(rData);')) вводит полную лексическую среду.

...