Reputation: 807
I am working on my worker remote method invocation and class instantiation and I was doing some eval research with closures. I came with the code bellow which I really like and I'll use it, but don't really understand why it works and how it works. Actually, I don't understand where the 'a' variable is stored and also where the name of it is stored as I can access it inside the function or by calling evals. Also, I would like to know what is its life cycle and when it will get destroyed. Is it a hack of JS engine or is it valid usage? I tested with IE10, IE11, Chrome, FF, Opera, Safari, Safari mobile... it works everywhere. I am so curious.
https://jsfiddle.net/bykwm1h3/2/
function scope(params) {
if (params) {
a = params;
} else {
console.log(a);
}
}
function evalInScope(code) {
eval.call(this, code)
}
// define variable - where is it defined?? definitely in the scope of the function as it is accessible there but, who really holds its instance?
evalInScope.call(scope, "var a;");
// setup variable values
scope([1,2,3]);
// print it out
evalInScope.call(scope, "console.log(a)");
// or print it out
scope();
Upvotes: 1
Views: 72
Reputation: 1074148
Your a
is a global variable, because you're doing an indirect eval
. When you do indirect eval
, the code you pass eval
is evaluated at global scope. var
at global scope creates global variables.
The more canonical way to do indirect eval is either to use a variable:
var x = eval;
x("code here");
or use the comma operator:
(0, eval)("code here");
Direct eval (eval("code here")
) evaluates the code you pass it within the scope in which the eval
call appears.
And yes: This business of direct vs. indirect eval
is confusing, surprising, and not consistent with how other functions work. It wasn't designed, it grew and was codified. :-)
If your goal was to evaluate the code within the scope
function, that's not what that code does. To do that, you'd use eval
within scope
:
function scope(code) {
eval(code);
}
You can prove to yourself a
is a global by seeing if it ended up as a property on the global object, which we can access via the window
global on browsers:
function scope(params) {
if (params) {
a = params;
} else {
console.log(a);
}
}
function evalInScope(code) {
eval.call(this, code)
}
console.log("a in window?", "a" in window); // false
evalInScope.call(scope, "var a;");
console.log("a in window?", "a" in window); // true
Upvotes: 4