Функция 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));
При этом посетитель потенциально может делать все, что угодно.
Чтобы ограничить выражения только математикой, вводимую строку нужно проверять при помощи регулярных выражений на наличие любых символов, кроме букв, пробелов и знаков пунктуации.
Комментарии
- Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
- Если ваш комментарий касается задачи -- откройте её в отдельном окне и напишите там.
- Комментарии без смысла, с рекламой или не о статье вообще - удаляются.