eval()

by 3 contributors:

This translation is incomplete. Please help translate this article from English.

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

Синтаксис

eval(string)

Параметры

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

Описание

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

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

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

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

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

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

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

If you use the eval function indirectly, by invoking it via a reference other than evalas of ECMAScript 5 it works at global scope rather than local scope; this means, for instance, that function declarations create global functions, and that the code being evaluated doesn't have access to local variables within the scope where it's being called.

function test() {
  var x = 2, y = 4;
  console.log(eval("x + y"));  // Direct call, uses local scope, result is 6
  var geval = eval;
  console.log(geval("x + y")); // Indirect call, uses global scope, throws ReferenceError because `x` is undefined
}

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

eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, third party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.

eval() is also generally slower than the alternatives, since it has to invoke the JS interpreter, while many other constructs are optimized by modern JS engines.

There are safer (and faster!) alternatives to eval() for common use-cases.

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

You should not use eval() to convert property names into properties. Consider the following example where the property of the object to be accessed is not known until the code is executed. This can be done with eval:

var obj = { a: 20, b: 30 };
var propname = getPropName();  // returns "a" or "b"

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

However, eval() is not necessary here. In fact, its use here is discouraged. Instead, use the property accessors, which are much faster and safer:

var obj = { a: 20, b: 30 };
var propname = getPropName();  // returns "a" or "b"
var result = obj[ propname ];  //  obj[ "a" ] is the same as obj.a 

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

JavaScript has first-class functions, which means you can pass functions as arguments to other APIs, store them in variables and objects' properties, and so on. Many DOM APIs are designed with this in mind, so you can (and should) write:

// instead of setTimeout(" ... ", 1000) use:
setTimeout(function() { ... }, 1000); 

// instead of elt.setAttribute("onclick", "...") use:
elt.addEventListener("click", function() { ... } , false); 

Closures are also helpful as a way to create parametrized functions without concatenating strings.

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

If the string you're calling eval() on contains data (for example, an array: "[1, 2, 3]"), as opposed to code, you should consider switching to JSON, which allows the string to use a subset of JavaScript syntax to represent data. See also Downloading JSON and JavaScript in extensions.

Note that since JSON syntax is limited compared to JavaScript syntax, many valid JavaScript literals will not parse as JSON. For example, trailing commas are not allowed in JSON, and property names (keys) in object literals must be enclosed in quotes. Be sure to use a JSON serializer to generate strings that will be later parsed as JSON.

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

For example, an extension designed to scrape contents of web-pages could have the scraping rules defined in XPath instead of JavaScript code.

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

If must run code, consider running it with reduced privileges. This advice applies mainly to extensions and XUL applications, which can use Components.utils.evalInSandbox for this.

Примеры

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

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

var x = 2;
var y = 39;
var z = "42";
eval("x + y + 1"); // returns 42
eval(z);           // returns 42 

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

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

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() вернет значение последнего выполняемого выражения

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 как строковое определение функции, включающее "(" и ")" как префикс и суффикс

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

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

Спецификация Статус Комментарий
ECMAScript 1st Edition. Standard Initial definition.
ECMAScript 5.1 (ECMA-262)
Определение 'eval' в этой спецификации.
Стандарт  
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'eval' в этой спецификации.
Стандарт  

Поддержка браузерами

Особенность Chrome Firefox (Gecko) Internet Explorer Opera Safari
Базовая поддержка (Да) (Да) (Да) (Да) (Да)
Особенность Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Базовая поддержка (Да) (Да) (Да) (Да) (Да) (Да)

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

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

Смотрите также

Метки документа и участники

Contributors to this page: KTatyana, bychek.ru, Bogdan92
Обновлялась последний раз: KTatyana,
Скрыть боковую панель