Multiple Variable Assignment Javascript Onclick

The function evaluates JavaScript code represented as a string.

The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.

Syntax

Parameters

A string representing a JavaScript expression, statement, or sequence of statements. The expression can include variables and properties of existing objects.

Return value

The completion value of evaluating the given code. If the completion value is empty, is returned.

Description

is a function property of the global object.

The argument of the function is a string. If the string represents an expression, evaluates the expression. If the argument represents one or more JavaScript statements,  evaluates the statements. Do not call to evaluate an arithmetic expression; JavaScript evaluates arithmetic expressions automatically.

If you construct an arithmetic expression as a string, you can use to evaluate it at a later time. For example, suppose you have a variable . You can postpone evaluation of an expression involving by assigning the string value of the expression, say "", to a variable, and then calling at a later point in your script.

If the argument of is not a string, returns the argument unchanged. In the following example, the constructor is specified and returns a 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 .

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

If you use the function indirectly, by invoking it via a reference other than , 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 }

Do not ever use !

is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run 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, a third-party code can see the scope in which was invoked, which can lead to possible attacks in ways to which the similar is not susceptible.

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

Additionally, modern javascript interpreters convert javascript to machine code. This means that any concept of variable naming gets obliterated. Thus, any use of eval will force the browser to do long expensive variable name lookups to figure out where the variable exists in the machine code and set it's value. Additonally, new things can be introduced to that variable through  such as changing the type of that variable, forcing the browser to reevaluate all of the generated machine code to compensate. However, there (thankfully) exists a very good alternative to eval: simply using window.Function. As an example of how you convert code using evil  to using  , see below.

Bad code with eval:

Better code without eval:

Comparing the two code snippets above, the two code snippets might seem to work the same way, but think again: the eval one is a huge amount slower. Notice  in the evaluated object. In the function without the eval, the object is being evaluated in the global scope, so it is safe for the browser to assume that  refers to  instead of a local variable called Date. But, in the code using , the browser cannot assume this since what if your code looked like the following:

Thus, in the  version of the code, the browser is forced to make the expensive lookup call to check to see if there are any local variables called . This is incredibly innefficient compared to .

In a related circumstance, what if you actually wanted your  function to be able to be called from the code inside . Should you just wimp out and fall back to ? Absolutely not, never ever. Instead try the aproach below.

function Date(n){ return ["Monday","Tuesday","Wednessday","Thursaday","Friday","Saturday","Sunday"][n%7 || 0]; } function runCodeWithDateFunction(obj){ return Function('"use strict";return (' + obj + ')')()( Date   ); } console.log(runCodeWithDateFunction( "function(Date){ return Date(5) }" ))

The code above may seem inefficiently slow because of the triple nested function, but let's analyse the benefits of the above efficient method:

1. It allows the code in the string passed to  to be minified.

2. Function call overhead is minimal, making the far smaller code size well worth the benefit

3.  more easily allows your code to utilize the performance buttering 

4. The code does not use , making it orders of magnitude faster than otherwise.

Lastly, let's examine minification. With using   as shown above, you can minify the code string passed to  far more efficiently because the function arguments names can be minified too as seen in the minified code below.

console.log(Function('"use strict";return(function(a){return a(5)})')()(function(a){ return"Monday Tuesday Wednessday Thursaday Friday Saturday Sunday".split(" ")[a%7||0]}));

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

Accessing member properties

You should not use 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, 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 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 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()]; }   return 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

Use functions instead of evaluating snippets of code

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.

Parsing JSON (converting strings to JavaScript objects)

If the string you're calling on contains data (for example, an array: ), 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.

Pass data instead of code

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

Run code with limited privileges

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

Examples

Using

In the following code, both of the statements containing return 42. The first evaluates the string ""; the second evaluates the string "".

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

Using to evaluate a string of JavaScript statements

The following example uses to evaluate the string . This string consists of JavaScript statements that open an alert dialog box and assign a value of 42 if is five, and assigns 0 to otherwise. When the second statement is executed, will cause these statements to be performed, and it will also evaluate the set of statements and return the value that is assigned to .

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 multiple 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

Last expression is evaluated

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);

as a string defining function requires "(" and ")" as prefix and suffix

var fctStr1 = 'function a() {}' var fctStr2 = '(function a() {})' var fct1 = eval(fctStr1) // return undefined var fct2 = eval(fctStr2) // return a function

Specifications

Browser compatibility

The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support Yes Yes1 Yes Yes Yes
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support Yes Yes Yes4 Yes Yes ?
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidiOS SafariSamsung InternetNode.js
Basic supportFull support YesFull support YesFull support 1Full support YesFull support YesFull support YesFull support YesFull support YesFull support YesFull support 4Full support YesFull support Yes ? Full support Yes

Legend

Full support
Full support
Compatibility unknown
Compatibility unknown

Firefox-specific notes

  • Historically 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.

See also

A few things here...

If you want to call a function when the onclick event happens, you'll just want the function name plus the parameters.

Then if your parameters are a variable (which they look like they are), then you won't want quotes around them. Not only that, but if these are global variables, you'll want to add in "window." before that, because that's the object that holds all global variables.

Lastly, if these parameters aren't variables, you'll want to exclude the slashes to escape those characters. Since the value of onclick is wrapped by double quotes, single quotes won't be an issue. So your answer will look like this...

There are a few extra things to note here, if you want more than a quick solution.

You looked like you were trying to use the + operator to combine strings in HTML. HTML is a scripting language, so when you're writing it, the whole thing is just a string itself. You can just skip these from now on, because it's not code your browser will be running (just a whole bunch of stuff, and anything that already exists is what has special meaning by the browser).

Next, you're using an anchor tag/link that doesn't actually take the user to another website, just runs some code. I'd use something else other than an anchor tag, with the appropriate CSS to format it to look the way you want. It really depends on the setting, but in many cases, a span tag will do. Give it a class (like class="runjs") and have a rule of CSS for that. To get it to imitate a link's behavior, use this:

This lets you leave out the href attribute which you weren't using anyways.

Last, you probably want to use JavaScript to set the value of this link's onclick attribute instead of hand writing it. It keeps your page cleaner by keeping the code of your page separate from what the structure of your page. In your class, you could change all these links like this...

While this won't work in some older browsers (because of the getElementsByClassName method), it's just three lines and does exactly what you're looking for. Each of these links has an anonymous function tied to them meaning they don't have any variable tied to them except that tag's onclick value. Plus if you wanted to, you could include more lines of code this way, all grouped up in one tidy location.

answered Nov 8 '12 at 9:25

0 thoughts on “Multiple Variable Assignment Javascript Onclick

Leave a Reply

Your email address will not be published. Required fields are marked *