In standard JS, Eval and window. Eval are different syntaxes!

Source: Internet
Author: User

The code must be executed globally in a recently written script. In this example, the window.exe script method is used in IE6, 8, and the window. Eval method is called for others.

It seems very simple and runs correctly. The A declared by Eval is only visible internally; the B declared by window. Eval is globally visible.

<script>
function A()
{
eval("var a=1");
window.eval("var b=1");
}

A();

alert(typeof a); //undefined
alert(typeof b); //number
</script>

However, in retrospect, it seems a little strange. Isn't eval the same function as window. Eval? Why is it different to add window? If eval internally determines the current this, this points to the window when eval and window. Eval are executed.

If the Variable P = Window. Eval is used, is P () the same as window. eval?

<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>

After testing, P () and window. eval () have the same effect and are all executed globally. And P = Window. eval and P = eval are both valid! This is obviously strange, but there are even more strange things behind it! If we use q = Eval, the results are totally unexpected:

<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>

Number is displayed! That is to say, P pointing to eval, but the actual effect is window. eval. They all execute code globally!

To verify whether it is a reference difference, we will perform another test:

<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, the executed by Eval is left inside, while the B executed by Q = Eval is global!

  

So I guess,The eval in standard JavaScript, perhaps the same as this, is both a keyword and a variable (function variable). If the keyword is called, that is, the literal eval (), it is executed in the current context; otherwise, the call is performed globally by referencing the variable. In this way, we can explain the differences between window. eval and Eval:Window. Eval is only an eval attribute in the window object and an attribute pointing to the eval function.. Like window. eval and window. ev_3, it is only one attribute, not literally eval.

  

To verify this guess, I checked the Firefox Script Engine source code. The real execution part of Eval is defined in evalkernel in jsobj. cpp:

bool
EvalKernel(JSContext *cx, uintN argc, Value *vp, EvalType evalType, JSStackFrame *caller,
JSObject *scopeobj)
{
...

/*
* Per ES5, indirect eval runs in the global scope. (eval is specified this
* way so that the compiler can make assumptions about what bindings may or
* may not exist in the current frame if it doesn't see '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 this function has an evaltype parameter, which determines whether Eval is running globally. If it is direct_eval, staticlevel indicates the current context; otherwise, staticlevel = 0 indicates global.

We found in jsinterp. cpp that evalkernel is called in direct_eval mode:

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;
}

Where directeval is called, it is the region where the keyword is defined:

}
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)
{

 

Obviously, Eval and new are both processed as keywords. That is to say, direct_eval is passed in only when the word "eval (...)" appears in the code, that is, it is executed in the current context.

Visible,The eval of ECMA-262 has the characteristic of keyword! But it is not a real keyword, because the keyword cannot be used as the object property name. For example, window. This and window. VaR are incorrect syntax. But eval can.

Assume that an eval variable is declared in the context and points to window. eval. So what will happen?

<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? Because this Eval is the original eval ~ All are executed internally. (The chrome exception is treated as an eval reference and the result is number)

But it does not mean that eval cannot be overwritten:

<script>
eval = alert;

function A()
{
eval("var a=1");     //var a=1
window.eval("var b=1"); //var b=1
}

A();
</script>

Normally, two dialog boxes are displayed.
Visible,In the context, as long as the eval points to the original function and is not overwritten, it has a keyword feature.Otherwise, it is a variable called eval. The code in begin_case (jsop_eval) {} In jsinterp. cpp also illustrates this.

P

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.