...

View Full Version : Is eval() necessary here, and if yes, how?



VIPStephan
11-29-2012, 06:12 PM
I’ve come across this ancient piece of JavaScript:


<script language="JavaScript">
function popUp(URL) {
day = new Date();
id = day.getTime();
eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=1,scrollbars=1,location=1,statusbar=1,menubar=1,resizable=1,width=700,height=500,left = 162,top = 134');");
}
</script>


What’s the purpose of the eval() here? I also don’t see any other reference to “page” in the source code from where I go this (I doubt that it is used in any other external script). So, what’s the point and why couldn’t I just run window.open() by itself?

The reason why I’m asking is because I want to update that script a little to validate in strict mode and JShint is complaining about eval().

007julien
11-29-2012, 06:34 PM
The second parameter of window open is optional.
Specifies the target attribute or the name of the window. The following values are supported:

_blank - URL is loaded into a new window. This is default
_parent - URL is loaded into the parent frame
_self - URL replaces the current page
_top - URL replaces any framesets that may be loaded
name - The name of the window
Then the eval("page"+Id) could be replace by a window["page"+id]

AndrewGSW
11-29-2012, 06:59 PM
I assume it is used to create page1354211652677 as a global variable that references the new window. But the only way to then use it is to re-construct the variable name using eval again, and the global variable id.

A way to avoid this would be to have a global array that stores the references to new windows - assuming popUp() is called more than once.

The id (a number) is used to name the new window anyway.. It shouldn't be just a number (although this might still work..). But the name is not much use, other than setting it as a target for a link.

felgall
11-29-2012, 07:28 PM
I assume it is used to create page1354211652677 as a global variable that references the new window.

Presumably by someone with very little JavaScript knowledge or they'd have coded it properly as window["page"+id] (as 007julien already said in the prior post) - since eval is almost completely unnecessary in JavaScript with only a few advanced situations where it is actually needed. Beginner and intermediate JavaScript never needs eval().

While eval() is still a valid command in strict JavaScript any variables defined inside the eval go out of scope when the eval finishes running which means it can no longer be used in situations such as this but can still be used in those advanced situations it is intended for.

VIPStephan
11-29-2012, 09:35 PM
The id (a number) is used to name the new window anyway.. It shouldn't be just a number (although this might still work..). But the name is not much use, other than setting it as a target for a link.

Hm, I wouldn’t know if/how the windows are referenced in this application. That function is called from several links and repeatingly clicking the same link(s) just opens new windows. Could be that they meant to always open a new window by adding a timestamp and not re-using an already open one but that would happen automatically if no target/name is provided, I suppose. I have no idea. Maybe I’ll just take the risk and change that function altogether.

Thanks for the info, guys.

felgall
11-29-2012, 09:46 PM
That function is called from several links and repeatingly clicking the same link(s) just opens new windows.

That means that the value in the second parameter of the window.open call isn't working. Where that value matches the name of a window that is already open then the page should open in that window rather than opening another window as you are not supposed to be able to have two windows with the same name.

VIPStephan
11-29-2012, 09:54 PM
That means that the value in the second parameter of the window.open call isn't working. Where that value matches the name of a window that is already open then the page should open in that window rather than opening another window as you are not supposed to be able to have two windows with the same name.

Well, I thought it is working because it creates a new date string everytime the link is clicked, and it is using that date string as the parameter value; echoing the window name in the console gives me a long number, apparently the Unix timestamp, which is different in each window.

felgall
11-29-2012, 10:39 PM
Well, I thought it is working because it creates a new date string everytime the link is clicked, and it is using that date string as the parameter value; echoing the window name in the console gives me a long number, apparently the Unix timestamp, which is different in each window.
Presumably there is subsequent processing that needs to reference those windows by those names - otherwise '_blank' would be a simpler alternative for that parameter.

AndrewGSW
11-29-2012, 10:54 PM
I apologise in advance if I have misunderstood something :thumbsup: .. but.. that function uses getTime() each time to name the window, which will be different on each occasion - so the same window will never be re-used.

If, as felgall advises, the variable created by eval() immediately goes out of scope, then no reference to the (new) window is retained. As far as I understand.. neither window['name'] nor windows['name'] (there is no windows collection..) can be used to reference a window.

(.. I don't think the variable created by eval goes out of scope..? But I await correction :) )


function init() {
eval('x=12');
}
window.onload = init;

<button onclick="alert(x);">Still there?</button>

Added: So window["page"+id] could reference an existing window, but it is referencing it by means of the global variable named 'page123456..' and not the name of the window - although they happen to be the same in this instance.

AndrewGSW
11-29-2012, 11:24 PM
..attempting to create a local variable with


eval('var x=12');
is more complicated as (my research tells me) some browsers will hoist it to the global scope.

AndrewGSW
11-30-2012, 12:09 AM
So, to answer your question :D I suggest replacing


eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=1,scrollbars=1,location=1,statusbar=1,menubar=1,resizable=1,width=700,height=500,left = 162,top = 134');");
with


window["page" + id] = window.open(URL, id, 'toolbar=1,scrollbars=1,location=1,statusbar=1,menubar=1,resizable=1,width=700,height=500,left = 162,top = 134');

possibly changing the name (2nd argument) from id to "page"+id (so it isn't just a number).

felgall
11-30-2012, 09:12 AM
(.. I don't think the variable created by eval goes out of scope..? But I await correction :) )

It is one of the changes that was made in the ECMAScript 5 specification. When you use strict JavaScript any variables defined in an eval go out of scope when the eval finishes - there is nothing you can do that requires an eval and also requires that something defined there continue to exist after the eval finishes.

The Mozilla page listing the changes describes it like this:


eval of strict mode code does not introduce new variables into the surrounding scope. In normal code eval("var x;") introduces a variable x into the surrounding function or the global scope. This means that, in general, in a function containing a call to eval every name not referring to an argument or local variable must be mapped to a particular definition at runtime (because that eval might have introduced a new variable that would hide the outer variable). In strict mode eval creates variables only for the code being evaluated, so eval can't affect whether a name refers to an outer variable or some local variable:

var x = 17;
var evalX = eval("'use strict'; var x = 42; x");
assert(x === 17);
assert(evalX === 42);

Note that JavaScript also now requires that you declare all variables in the scope you intend to use them in so that mistyping a variable name or failing to declare one will not pollute the global namespace.

eval('text' + varfld) can always be rewritten as window['text+ varfld] if it is outside a function. Inside a function called myfunc eval('text' + varfld) can always be rewritten as myfunc['text+ varfld]

The only situation I have ever come across where an eval is necessary is inside a Function.prototype method that is dynamically reqriting all the functions in your page and there the eval is needed to turn the text version of the rewritten function back into code - and since the eval is wrapped around the entire content of the function it has the same scope as the function and nothing defined within it needs to exist afterwards.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum