The eval()
function evaluates JavaScript code represented as a string.
eval(string)
string
The completion value of evaluating the given code. If the completion value is empty, undefined
is returned.
eval()
is a function property of the global object.
The argument of the eval()
function is a string. If the string represents an expression, eval()
evaluates the expression. If the argument represents one or more JavaScript statements, eval()
evaluates the statements. Do not call eval()
to evaluate an arithmetic expression; JavaScript evaluates arithmetic expressions automatically.
If you construct an arithmetic expression as a string, you can use eval()
to evaluate it at a later time. For example, suppose you have a variable x
. You can postpone evaluation of an expression involving x
by assigning the string value of the expression, say "3 * x + 2
", to a variable, and then calling eval()
at a later point in your script.
If the argument of eval()
is not a string, eval()
returns the argument unchanged. In the following example, the String
constructor is specified, and eval()
returns a String
object rather than evaluating the string.
eval(new String('2 + 2')); // returns a String object containing "2 + 2" eval('2 + 2'); // returns 4
You can work around this limitation in a generic fashion by using 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 eval
, as of ECMAScript 5 it works in the global scope rather than the 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; // equivalent to calling eval in the global scope console.log(geval('x + y')); // Indirect call, uses global scope, throws ReferenceError because `x` is undefined (0, eval)('x + y'); // another example of Indirect call }
eval
needlessly!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
You can even use this method to access descendant properties. Using eval()
this would look like:
var obj = {a: {b: {c: 0}}}; var propPath = getPropPath(); // returns e.g. "a.b.c" eval( 'var result = obj.' + propPath );
Avoiding eval()
here could be done by splitting the property path and looping through the different properties:
function getDescendantProp(obj, desc) { var arr = desc.split('.'); while (arr.length) { obj = obj[arr.shift()]; } return obj; } var obj = {a: {b: {c: 0}}}; var propPath = getPropPath(); // returns e.g. "a.b.c" var result = getDescendantProp(obj, propPath);
Setting a property that way works similarly:
function setDescendantProp(obj, desc, value) { var arr = desc.split('.'); while (arr.length > 1) { obj = obj[arr.shift()]; } obj[arr[0]] = value; } var obj = {a: {b: {c: 0}}}; var propPath = getPropPath(); // returns e.g. "a.b.c" var result = setDescendantProp(obj, propPath, 1); // test.a.b.c will now be 1
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 parameterized functions without concatenating strings.
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 you 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
In the following code, both of the statements containing eval()
return 42. The first evaluates the string "x + y + 1
"; the second evaluates the string "42
".
var x = 2; var y = 39; var z = '42'; eval('x + y + 1'); // returns 42 eval(z); // returns 42
eval
to evaluate a string of JavaScript statementsThe following example uses eval()
to evaluate the string str
. This string consists of JavaScript statements that open an alert dialog box and assign z
a value of 42 if x
is five, and assigns 0 to z
otherwise. When the second statement is executed, eval()
will cause these statements to be performed, and it will also evaluate the set of statements and return the value that is assigned to 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));
If you define mutiple values then the last value is returned.
var x = 5; var str = "if (x == 5) {console.log('z is 42'); z = 42; x = 420; } else z = 0;"; console.log('x is ', eval(str)); // z is 42 x is 420
eval()
returns the value of the last expression evaluated.
var str = 'if ( a ) { 1 + 1; } else { 1 + 2; }'; var a = true; var b = eval(str); // returns 2 console.log('b is : ' + b); a = false; b = eval(str); // returns 3 console.log('b is : ' + b);
eval
as a string defining function requires "(" and ")" as prefix and suffixvar fctStr1 = 'function a() {}' var fctStr2 = '(function a() {})' var fct1 = eval(fctStr1) // return undefined var fct2 = eval(fctStr2) // return a function
Specification | Status | Comment |
---|---|---|
ECMAScript 1st Edition (ECMA-262) | Standard | Initial definition. |
ECMAScript 5.1 (ECMA-262) The definition of 'eval' in that specification. | Standard | |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'eval' in that specification. | Standard | |
ECMAScript Latest Draft (ECMA-262) The definition of 'eval' in that specification. | Draft |
Feature | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Basic support | Yes | Yes | Yes | Yes | Yes | Yes |
Feature | Android webview | Chrome for Android | Edge mobile | Firefox for Android | Opera Android | iOS Safari | Samsung Internet |
---|---|---|---|---|---|---|---|
Basic support | Yes | Yes | Yes | Yes | Yes | Yes | ? |
eval()
had an optional second argument, specifying an object in whose context the evaluation was to be performed. This argument was non-standard, and was definitely removed from Firefox 4. See bug 531675.
© 2005–2018 Mozilla Developer Network and individual contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval