On Thu, 2005-09-01 at 13:36 -0600, Jason Johnston wrote:
> On Thu, 2005-09-01 at 20:11 +0200, Thorsten Scherler wrote:
> > Hi all,
> >
> > I have a problem with the evalFunc() in flow. I think that not only the
> > eval() function is broken, but as well the evalFunc().
> >
> > Add the following to your flow script:
> >
> > var genericDoc;
> > scriptString= "genericDoc='testing';";
> > evalFunc = new Function ("genericDoc",scriptString);
> > evalFunc(genericDoc);
> > print("xxx ",genericDoc);
> >
> > The sysout gives you:
> > xxx undefined
> >
> > That is not what the following link says (thx again Jason Johnston, for
> > this awesome link):
> > http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function#Created_By
> > "However, if you pass an object as a parameter to a function and the
> > function changes the object's properties, that change is visible outside
> > the function."
>
> Your code is actually not "changing the object's properties". If you
> were to try genericDoc.property='value' then that would work since
> you're changing a property of the object referred to by the genericDoc
> variable. However your code is actually changing which object
> genericDoc refers to, which is not the same thing. Remember, variables
> are not objects but *pointers to* objects.
>
> Now, you might expect that changing genericDoc's value inside the
> function would also change the value of the genericDoc variable from
> outside the function. But this is not the case in your example because
> function arguments are treated as variables local to the function, so
> the genericDoc variable (the named argument) inside the function is
> different than the genericDoc variable outside the function.
>
> If you want genericDoc within the function to be the same variable as
> genericDoc outside, you can rely on closures. This basically means that
> when a function is created (as happens with new Function("")) it creates
> a closure so that the code within the function has access to the entire
> scope of where it was created. So:
>
> var genericDoc;
> scriptString= "genericDoc='testing';";
> evalFunc = new Function (scriptString);
> evalFunc();
> print("xxx ",genericDoc);
>
> ...should work, since evalFunc automatically gets access to the
> genericDoc variable since it was in scope when evalFunc was created.
>
> Hope this makes at least a little sense. It's taken me a long while to
> get a handle on the complexity of closures.
:)
Thanks for this comprehensive explanation, yes that makes a lot of sense
(after reading it a couple of times). ;-)
The only thing is the scope that does not seem to work, like you
described, but using the properties is working. :) The only important
thing is that the var is initialized (like "var genericDoc={doc:null};")
otherwise (for "var genericDoc;") you get "The undefined value has no
properties.".
Here is the roundtrip that I did. Thanks again Jason, you have been a
great help.
1) I tried:
var genericDoc="doh!";
print('before ',genericDoc);
var evalFunc = new Function ("print('/testing',genericDoc)");
evalFunc();
print("xxx ",genericDoc);
It gives:
sysout: before doh!
cocoon: org.mozilla.javascript.EcmaError: "genericDoc" is not defined.
2) Now changing the code to:
var genericDoc="doh!";
print('before ',genericDoc);
var evalFunc = new Function
("genericDoc","print('/testing',genericDoc)");
evalFunc(genericDoc);
print("xxx ",genericDoc);
It gives (sysout):
before doh!
/testing doh!
xxx doh!
3) Changing it to:
var genericDoc="doh!";
print('before ',genericDoc);
var evalFunc = new Function ("genericDoc","genericDoc='working'");
evalFunc(genericDoc);
print("xxx ",genericDoc);
Gives (sysout):
before doh!
xxx doh!
4) Changing it to:
var genericDoc="doh!";
print('before ',genericDoc);
var evalFunc = new Function ("genericDoc='working'");
evalFunc();
print("xxx ",genericDoc);
gives:
sysout: before doh!
cocoon: java.lang.ClassCastException
5) Changing:
var genericDoc={value:"doh!"};
print('before ',genericDoc.value);
var evalFunc = new Function ("genericDoc.value='working'");
evalFunc();
print("xxx ",genericDoc.value);
gives:
sysout: before doh!
cocoon: org.mozilla.javascript.EcmaError: "genericDoc" is not defined.
6) Changing:
var genericDoc={value:"doh!"};
print('before ',genericDoc.value);
var evalFunc = new Function
("genericDoc","genericDoc.value='working'");
evalFunc(genericDoc);
print("xxx ",genericDoc.value);
gives (sysout):
before doh!
xxx working
salu2
--
thorsten
"Together we stand, divided we fall!"
Hey you (Pink Floyd)