Мастер-классы по Javascript Екатеринбург Ростов-на-Дону Москва Узнать больше...
Содержание (скрыть) Содержание (показать)

Запуск кода из строки "eval"

  1. Пример
  2. Запуск в глобальном контексте
  3. Пример использования: JSON
  4. Итого

Функция eval(code) позволяет выполнить код, переданный ей в виде строки. При этом используется текущая область видимости.

Пример

Пример работы eval:

var a = 1;

(function() {

  var a = 2; 
  
  eval(' alert(a) '); // 2

})()

Вызов eval возвращает последнее вычисленное выражение:

alert( eval('1+1') )

В современном JavaScript этот оператор применяется очень редко, так как в правильно организованной программе в виде строк передаются данные, а не код.

Тем не менее, иногда он бывает полезен.

Запуск в глобальном контексте

Доступ к локальным переменным из eval не нужен почти никогда.

Существуют различные трюки, которые позволяют запускать eval в глобальной области видимости, то есть без доступа к локальным переменным.

Например, можно вызвать eval не напрямую, а через window.eval. При этом область видимости для такого кода будет window, это предусмотрено в спецификации языка.

Этот код работает во всех современных браузерах, кроме IE<9.

var a = 1;

(function() {

  var a = 2; 
  
  window.eval(' alert(a) '); // 1, везде кроме IE<9

})();

В старых IE можно применить нестандартную фунцию execScript, чтобы решить проблему, но она, в отличие от eval, не возвращает значение:

*!*
function globalEval(code) {
  window.execScript ? execScript(code) : window.eval(code);
}
*/!*

var a = 1;

(function() {

  var a = 2; 
  
  globalEval(' alert(a) '); // 1, во всех браузерах

})();

Если нужно запустить код и передать ему локальное значение, и получить результат — используют new Function:

var a = 1;

(function() {

  var a = 2; 
  
  // код функции не обращается к локальным переменным
  // вместо этого он принимает аргумент 
  var f = new Function('x', 'alert(x)'); 

  f(a); // 2

})();

Кстати, в примере выше new Function и не может, даже теоретически, обратиться к локальной переменной a, т.к. областью видимости функций, созданных через new Function, является глобальный объект.

Пример использования: JSON

Допустим, мы хотим получить данные с сервера. Они присылаются в виде строки, содержащей JavaScript-объект. Функция eval позволяет прочитать их:

var str = "{name: 'Вася', permission: { canRead: true }}";

*!*
var obj = eval("("+str+")");
*/!*

alert(obj.name); // Вася
alert(obj.permission.canRead); // true

Зачем скобки в eval("("+str+")") ?

Чтобы получить значение, нужно сделать eval, прибавив к строке скобки. Почему не просто eval(str)?..

Дело в том, что просто код {name: ...} при выполнении выдаст ошибку. Попробуйте сделать такой скрипт, будет ошибка:

{ name: 'Вася' }
JavaScript подумает, что скобки — это блок кода, а name — это метка. В общем, воспримет это совсем не как объект.

Если же добавить скобки, то интерпретатор явно видит, что получил выражение:

( {name: 'Вася'} ) // в скобках может быть только выражение
Функция eval возвращает последнее вычисленное выражение, то есть наш объект.
var obj = eval( "( {name: 'Вася'} )" )
alert( obj.name );  // Вася

Передача объектов в JavaScript’овой записи называется «формат JSON» (JavaScript Object Notation). Хотя синтаксис JSON немного отличается, он строже. В этом формате обязательно нужно ставить двойные кавычки у названий свойств: не {name:'Вася'}, а {"name":"Вася"}.

Для работы с JSON в современных браузерах (кроме IE<8) существуют отдельные функции, но если с сервера приходит ещё и код (а такое бывает, например приходят скомпилированные JavaScipt-шаблоны) то здесь eval и конструктор new Function незаменимы.

Итого

  • Функция eval(str) выполняет код и возвращает последнее вычисленное выражение. В современном JavaScript она используется редко.
  • Она выполняется в текущей области видимости, поэтому может получать и изменять локальные переменные, но это нехорошо. Если код выполняемый всё же должен взаимодействовать с локальными переменными — используйте new Function.
  • Для запуска в глобальной области достаточно обратиться к eval не напрямую. Способ window.eval(code) вполне подойдёт. Это не работает в старых IE, но там есть (только IE) функция execScript.

Напишите интерфейс, который принимает математическое выражение (prompt) и возвращает его результат.

Интерфейс может допускать использование любых функций.

Демо в новом окне: tutorial/intro/eval-calc.html

Решение
Решение

Вычислить любое выражение нам поможет eval:

var expr = prompt("Введите выражение?", '2*3+2');

alert(eval(expr));
При этом посетитель потенциально может делать все, что угодно.

Чтобы ограничить выражения только математикой, вводимую строку нужно проверять при помощи регулярных выражений на наличие любых символов, кроме букв, пробелов и знаков пунктуации.

См. также:

Комментарии

  1. Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  2. Если ваш комментарий касается задачи -- откройте её в отдельном окне и напишите там.
  3. Комментарии без смысла, с рекламой или не о статье вообще - удаляются.
Наверх

Содержание

Реклама

Нашли опечатку?

Нашли опечатку на сайте? Что-то кажется странным?
Выделите соответствующий текст и нажмите Ctrl+Enter!

Последние Комментарии

Помоги другим!

Помоги другим узнать о хорошей статье!