2

I'm debugging and upgrading some legacy PHP and JavaScript code and I've found some eval() functions I cannot get rid of. Coming from desktop programming environment, with compiled languages such as C/C++ I've never used the eval() function in javascript mainly because I didn't know of its existence. I've been googling a while and from all that I've read I understand that eval() evaluates a string as if it was legit javascript code and executes it. I've managed to get rid of eval() functions which were being used to access dynamic properties and decoding JSON objects, however there's a fairly advanced (and obscure) class definition which uses eval() that I haven't been able to defeat.

Sample code:

 function Ddl(N) {
   this.lyr = document.getElementById(N);
   this.obj = N+"DDL_Lyr";
   eval(this.obj+"=this");
   this.lyr.setAttribute("onchange", this.obj+".onChange();");
 }

This function is an object constructor. DDL objects are used in the web page as:

 ddl_name = new Ddl('id_of_select');
 ddl_name.onChange = event_function;

For all that I know, eval(this.obj + "=this") should be the same as this.obj = this; but then the onchange event function event_function is not fired. I haven't been able to guess why using firebug. If I use this.obj = this I can see the value of this.obj changing from id_of_selectDDL_Lyr to a pointer to the DDL object itself so I can figure why setAttribute fails, but using the eval() function this.obj doesn't look to reflect the changes as code is executed, it always remains as 'id_of_selectDDL_Lyr', however it's doing something since if I comment it out the onchange event is not fired.

I suspect it may be related to local or global scope, since I've read that eval() calls are executed in a different scope, but I don't know how to ckeck it nor I know how to replace eval() with normal javascript code.

Joseph
  • 117,725
  • 30
  • 181
  • 234
  • Looks like some form of object cloning with the additional binding of the onchange event.Take a look at this discussion: http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-a-javascript-object – primavera133 May 09 '12 at 09:23
  • Did you try `this.obj = window`? Which you don't really need btw if your `onChange()` function is in the global scope. – Florian Margaine May 09 '12 at 09:28
  • As far as I can see that eval could be replaced with `window[this.obj]=this`, but I suggest you try using console.log to record some sample data first to confirm there is no unexpected behaviour. – scragar May 09 '12 at 09:30
  • I've tried clonning the object with MooTools `Object.clone(obj)` since the page is already using MooTools, but it's the same behaviour as `this.obj = this`, so is `this.obj` changes to a pointer in firebug. It doesn't work. I've tried `this.obj = window` and `window.obj = this` (which had more sense to me) but neither are working. :( –  May 09 '12 at 09:34

2 Answers2

1

I think this code is equivalent:

function Ddl(N) {
   var self = this;
   this.lyr = document.getElementById(N);
   this.obj = N + "DDL_Lyr";
   window[this.obj] = this;
   this.lyr.onchange = function() {
       self.onChange();
   };
}

The eval is not saying this.obj = this, it's creating a new global variable with the name "N + DDL_Lyr" (where N is variable).

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • This is only equivalent if the string value in `this.obj` is the same as the name of a variable in the global scope... the variable could be in an outer scope that isn't the global scope. – Dagg Nabbit May 09 '12 at 09:48
  • @GGG it _could_, but I don't think it is, in this case. – Alnitak May 09 '12 at 09:50
  • I don't think so either, but the OP should make sure. – Dagg Nabbit May 09 '12 at 09:50
  • scragar and Alnitak answers are rigth. Using `window[this.obj] = this` solved the question. Thank you very much you all! :D –  May 09 '12 at 10:04
  • @RafaRequeni I'd advise using the modified `.onchange` code from my answer too - setting the text content of an attribute also results in a (hidden) eval call. – Alnitak May 09 '12 at 10:22
-1

change

this.lyr.setAttribute("onchange", this.obj+".onChange();");

to

this.lyr.onchange = this.obj+".onChange();";
tuoxie007
  • 1,234
  • 12
  • 10
  • 2
    AFAIK that won't work - when setting the `onchange` property you have to supply a function reference, not a string. – Alnitak May 09 '12 at 09:33