JS Function-constructor re-parsed everytime?

风流意气都作罢 提交于 2019-12-06 02:48:34

What they wanted to highlight is that the JS parser needs to its work every single time the Function constructor is called - basically just the obvious. There is no caching of the passed code string involved.

This is relevant [only] when compared with closures. Suppose we have these two functions:

function makeAlerterParse(string) {
    return Function("alert("+JSON.stringify(string)+");");
}
function makeAlerterClosure(string) {
    return function alerter() { alert(string); };
}

Both function declarations will be parsed when the script is loaded - no surprises. However, in the closure also the alerter function expression is parsed already. Let's make some alerters:

var alerter1 = makeAlerterParser("1"); // Here the parser will be invoked
alerter1(); // no parsing, the function is instantiated already and 
alerter1(); // can be interpreted again and again.

var alerter2 = makeAlerterClosure("2"); // Here, no parser invocation -
alerter2(); // it's just a closure whose code was already known
alerter2(); // but that has now a special scope containing the "2" string

Still no surprise? Good, then you have already understood everything. The warning is only that an explicit invocation like

for (var fnarr=[], i=0; i<100; i++)
    fnarr[i] = makeAlerterParse(i);

will really be 100 invocations of the JS parser, while the closure version comes for free.

My understanding is that with a function constructor, the engine stores the body string as a string rather than as the function it creates; thus, it would need to be reparsed (converted from a string to a function) every time you use it.

Whereas a function declaration or expression parses it the first time, and stores it in memory as a function, so whenever you use it, it goes to the memory location of the function to access it.

If we look at your example, I think it could be read like this:

var bar = 'FOO!';
var foo = (new Function("return(function() {\n\talert(bar);\n});"))();
// function() {\n\talert(bar);\n} is a function declaration, so when it's evaluated
// the first time, the engine pulls out the function and stores it as an anonymous function

bar = 'FOO! again';
foo(); //The segment "function() {\n\talert(bar);\n}" of the function body string is not re-parsed.

'FOO! again' is the expected output since the function just references the variable bar, so once the foo is constructed, it just points to the variable as opposed to taking its value.

I think foo would be stored something like this:

"return function_location"

Which would get parsed every time it's executed.

In your last example, it doesn't alert 'FOO! again more' because when you used the constructor, it saved it as a string rather than a pointer to the variable. But what's interesting about your last example is that it stores the outer variable as a string, yet keeps the inner variable as it is.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!