eval()
======

**Предупреждение:** Выполнение кода JavaScript с текстовой строки - это невероятный риск для безопасности. Злоумышленнику слишком легко запустить какой угодно код, когда вы используете `eval()`. Смотрите Никогда не используйте eval()!, ниже.

Метод **`eval()`** выполняет JavaScript-код, представленный строкой.

Интерактивный пример
--------------------

Синтаксис
---------
```

eval(string)
```

### Параметры

`string`

Строка, представленная JavaScript выражением, оператором или последовательностью операторов. Выражение может содержать переменные и свойства существующих объектов.

### Возвращаемое значение

Возвращает значение выполнения кода, переданного в функцию в виде строки. Если код не возвращает ничего - будет возвращено значение `undefined`.

Описание
--------

`eval()` - функция глобального объекта.

Аргумент функции `eval()` - строка. `eval()` исполняет содержащееся в строке выражение, один или несколько операторов JavaScript. Не стоит вызывать `eval()` для определения значения арифметического выражения; JavaScript вычисляет их автоматически.

`eval()` можно использовать для вычисления значения арифметического выражения, записанного в строковом виде, на более поздней стадии исполнения. Предположим, существует переменная `x`. Можно отложить вычисление выражения, в котором содержится `х`, если присвоить переменной это выражение в виде строки (допустим, "`3 * x + 2`"), а затем вызвать `eval()` в более поздней точке кода.

Если аргумент, переданный `eval()`, не является строкой, `eval()` возвращает его неизменным. В следующем примере определён конструктор `String`, и `eval()` не вычисляет значение выражения, записанного в строковом виде, а возвращает объект типа `String`.


```js
eval(new String("2 + 2")); // возвращает объект типа String, содержащий "2 + 2"
eval("2 + 2"); // возвращает 4
```


Это ограничение легко обойти при помощи `toString()`.


```js
var expression = new String("2 + 2");
eval(expression.toString());
```


Если вы используете `eval` косвенно, вызовом его через ссылку, а не просто `eval`, в ECMAScript 5 это работает в глобальной области видимости, а не в локальной; это значит, что `eval` будет вызван в глобальной области видимости, а код будет выполнен с отсутствием доступа к локальным переменным в пределах области видимости, где он был вызван.


```js
function test() {
  var x = 2,
    y = 4;
  console.log(eval("x + y")); // Прямой вызов, использует локальную области видимости, результат - 6
  var geval = eval;
  console.log(geval("x + y")); // Непрямой вызов, использует глобальную область видимости, бросит ReferenceError, т.к. `x` - не определён
}
```

`Не используйте eval без необходимости!`
----------------------------------------

`eval()` - опасная функция, которая выполняет код, проходящий со всеми привилегиями вызывателя. Если вы запускаете `eval()` со строкой, на которую могут влиять злоумышленники, то вы можете запустить вредоносный код на устройство пользователя с правами вашей веб-страницы/расширения. Наиболее важно, код третьей стороны может видеть область видимости, в которой был вызван `eval()`, что может может привести к атакам, похожим на `Function`.

`Также eval()`, как правило, медленнее альтернатив, так как вызывает интерпретатор JS, тогда как многие другие конструкции оптимизированы современными JS движками.

Есть безопасные (и быстрые!) альтернативы `eval()` для общих случаев использования.

### Доступ к свойствам

Вам не следует использовать `eval()`, чтобы конвертировать имена свойств в свойства. Рассматривая следующий пример, где свойство объекта используемое для доступа неизвестно до выполнения кода. Это можно сделать с eval:


```js
var obj = { a: 20, b: 30 };
var propname = getPropName(); // возвращает "a" или "b"

eval("var result = obj." + propname);
```


Однако, `eval()` здесь не нужен. По факту, использование здесь его удивляет. Вместо него используйте доступ к свойствам, который быстрее и безопаснее:


```js
var obj = { a: 20, b: 30 };
var propname = getPropName(); // возвращает "a" или "b"
var result = obj[propname]; // obj[ "a" ] то же, что и obj.a
```

### Используйте функции вместо исполнения фрагментов кода

У JavaScript функции первого класса, что значит, что вы можете передавать функции как аргументы, хранить их в переменных или свойствах объектов и так далее. Многие DOM API созданы с учётом этого, так что вы можете (и вам следует) писать:


```js
// вместо setTimeout(" ... ", 1000) :
setTimeout(function() { ... }, 1000);

// вместо elt.setAttribute("onclick", "...") использовать:
elt.addEventListener("click", function() { ... } , false);
```


Замыкания также полезны как способ создания функций с параметрами без конкатенации строк.

### Разбор JSON (конвертирование строк в JavaScript объекты)

Если строка, переданная в `eval()`, содержит данные (к примеру, массив: `"[1, 2, 3]"`), а не код, вам следует рассмотреть JSON, позволяющий строке использовать подмножество JavaScript синтаксиса для представления данных. Смотрите также: Загрузка JSON и JavaScript в расширениях.

Заметьте, что синтаксис JSON ограничен в сравнении с JavaScript синтаксисом, многие валидные JavaScript литералы не распарсятся в JSON. К примеру, лишние запятые в конце выражений не разрешены в JSON, а имена свойств (ключи) в объектах должны быть в двойных кавычках. Будьте уверены использовать сериализацию JSON для создания строк, которые потом будут разбираться как JSON.

### Передавайте данные вместо кода

К примеру, расширение, созданное изменять содержимое веб-страниц, должно иметь правила, определённые в XPath (en-US), а не JS коде.

### Выполняйте код с ограниченными правами

Если выполнять код всё-таки необходимо, желательно это делать с уменьшенными привелегиями. Этот совет подходит, главным образом, к расширениям и XUL приложениям, которые могут использовать Components.utils.evalInSandbox.

Примеры
-------

### Использование `eval`

В следующем коде оба выражения содержат `eval()`, возвращающий 42. Первое определяется строкой "`x + y + 1`"; второе - строкой "`42`".


```js
var x = 2;
var y = 39;
var z = "42";
eval("x + y + 1"); // возвращает 42
eval(z); // вернёт 42
```

### Использование `eval` для исполнения строки, содержащей операторы JavaScript

Следующий пример использует `eval()` для получения значения выражения `str`. Эта строка состоит из JavaScript выражений, печатающих в консоль, и, если x равен пяти, призывающих z значение 42, или 0 в противном случае. Когда второе выражение будет исполнено, `eval()` будет считать выражения выполненными, а также это установит значение выражению переменной z и вернёт его.


```js
var x = 5;
var str = "if (x == 5) {console.log('z is 42'); z = 42;} else z = 0; ";

console.log("z is ", eval(str));
```

### Последнее выражение выполняется

`eval()` вернёт значение последнего выполняемого выражения


```js
var str = "if ( a ) { 1+1; } else { 1+2; }";
var a = true;
var b = eval(str); // вернёт 2

console.log("b is : " + b);

a = false;
b = eval(str); // вернёт 3

console.log("b is : " + b);
```

### `eval` как строковое определение функции, включающее "(" и ")" как префикс и суффикс


```js
var fctStr1 = "function a() {}";
var fctStr2 = "(function a() {})";
var fct1 = eval(fctStr1); // вернёт undefined
var fct2 = eval(fctStr2); // вернёт функцию
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-eval-x |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### Gecko-специфичные замечания

* Исторически `eval()` имел второй необязательный аргумент, указывающий на то, в контексте какого объекта будет выполняться выражение. Этот аргумент не был стандартизован и был удалён из SpiderMonkey в Gecko 1.9.1 (Firefox 3.5). См. Firefox bug 442333.
Смотрите также
--------------

* `uneval()` (en-US)
* Доступ к свойствам