It looks very simple and runs correctly. A of the Eval declaration is only visible internally; Window.eval declared B is globally visible.
The code is as follows |
Copy Code |
<script> function A () { Eval ("var a=1"); Window.eval ("var b=1"); } A (); Alert (typeof a); Undefined Alert (typeof B); Number </script> |
But it was a bit weird to think about it afterwards. Eval and window.eval are not the same function, why add window. Meaning is different? If Eval internally determines the current this, then when Eval and Window.eval execute, this is all pointing to window.
If you use a variable p=window.eval, is P () and Window.eval () still the same?
code is as follows |
copy code |
<script Function A () { var p = window.eval; alert (p = = window.eval); //true alert (p = = eval); //true eval ("var a=1"); p ("var b=1"); } A (); Alert (typeof a); //undefined Alert (typeof b); //number </script |
Tested, P () and window.eval () effect exactly the same, are all in the global execution. and p = = = Window.eval and P = = eval are set up at the same time! It's obviously strange, but there's something even more strange in the back! If we use q=eval, the result is completely unexpected:
The code is as follows |
Copy Code |
<script> function A () { var p = window.eval; var q = eval; P ("var a=1"); Q ("var b=1"); } A (); Alert (typeof a); Number Alert (typeof B); Number </script> |
All the number! are showing. In other words, pointing to eval p, the actual effect is window.eval. They are all executing code in the global!
To verify the difference between references, let's do one more test:
The code is as follows |
Copy Code |
<script> function A () { var q = eval; Q ("var b=1"); Eval ("var a=1"); } A (); Alert (typeof a); Undefined Alert (typeof B); Number </script> |
Obviously, eval execution's A is left inside, while Q=eval B is global!
So I speculate that the eval in standard JavaScript, like this, is both a keyword and a variable (a function variable). If the keyword is invoked, that is, the literal eval (), then executes in the current context, otherwise, by invoking the variable reference, it is executed globally. This explains the difference between Window.eval and eval: Window.eval is just a property called eval in the Window object, a property that points to the Eval function. As with Window.eval2,window.eval3, just one attribute, not the literal eval.
To verify this, I looked at the FireFox script engine source. Where the eval real execution section is defined in the Evalkernel in Jsobj.cpp:
The code is as follows |
Copy Code |
bool Evalkernel (Jscontext *cx, Uintn argc, Value *VP, Evaltype evaltype, Jsstackframe *caller, Jsobject *scopeobj) { ... /* * per ES5, indirect eval runs in the global scope. (The eval is specified this * Way so this compiler can make assumptions about what bindings may or * May isn't exist in the current frame if it doesn ' eval '.) */ UINTN Staticlevel; if (Evaltype = = Direct_eval) { Staticlevel = Caller->script ()->staticlevel + 1; } else { /* Pretend that we ' re top level. */ Staticlevel = 0; Js_assert (Scopeobj = = Scopeobj->getglobal ()); Js_assert (Scopeobj->isglobal ()); } ... } |
Obviously, you find that there is a parameter called Evaltype in this function, and it is this parameter that determines whether the eval is running globally. If the Direct_eval,staticlevel is the current context, otherwise the staticlevel=0 is the global.
And we found it in jsinterp.cpp. Call Evalkernel in Direct_eval mode:
code is as follows |
copy code |
bool Directeval (Jscontext *cx, jsfunction *evalfun, UInt32 argc, Value *vp) { ... jsobject *scopechain = getscopechainfast (CX, Caller, Jsop_eval, Jsop_eval_length + jsop_lineno_length); if (!scopechain | |!) Evalkernel (CX, ARGC, VP, Direct_eval, Caller, Scopechain)) return False ; CX->REGS->SP = VP + 1; return true; } |
The place where the call Directeval is defined is exactly the area of the keyword:
The code is as follows |
Copy Code |
} End_case (jsop_new) Begin_case (Jsop_eval) { ARGC = GET_ARGC (regs.pc); VP = regs.sp-(argc + 2); if (! Isfunctionobject (*VP, &callee)) Goto Call_using_invoke; Newfun = Callee->getfunctionprivate (); if (! Isbuiltinevalfunction (Newfun)) Goto Call_using_invoke; if (! Directeval (CX, Newfun, ARGC, VP)) Goto error; } End_case (Jsop_eval) Begin_case (Jsop_call) Begin_case (jsop_funapply) Begin_case (Jsop_funcall) { |
It is clear that eval, like the new one, is treated as a keyword. In other words, only the "eval (...)" appears in the code. These words are passed into the direct_eval, which is executed within the current context.
As you can see, ECMA-262 's eval has the character of a keyword! But it's not really a keyword, because the keyword is not available as an object property name, such as Window.this,window.var is the wrong syntax. But Eval can.
So if you declare a variable in the closure that is called Eval, and point to Window.eval. So what happens?
The code is as follows |
Copy Code |
<script> function A () { var eval = window.eval; Eval ("var a=1"); Eval ("var b=1"); } A (); Alert (typeof a); Undefined Alert (typeof B); Undefined </script> |
Why is it undefined? Since this eval is the original eval, it is all executed internally.
But it does not mean that Eval cannot be overwritten:
The code is as follows |
Copy Code |
<script> eval = alert; function A () { Eval ("var a=1"); var a=1 Window.eval ("var b=1"); var b=1 } A (); </script> |
A normal pop-up two dialog box.
It is obvious that in a context where eval keeps pointing to the original function and not being overwritten, it has a feature of the keyword; otherwise, it's a variable called eval. The code in Begin_case (Jsop_eval) {} In Jsinterp.cpp also illustrates