How to talk about early return with a variable defined after

I was looking at the JS library code and saw this template:

function module() { function func() { //... definedAfter(); //... } return func; var x = "...."; function definedAfter() { //... console.log(x); //outputs undefined //... } } 

The Google Closure compiler places the variable x as unused code, which seems reasonable, but it is interesting that the variable is declared, but with the value undefined (due to the rise).

Is this a bug in the library? Or is there some subtle behavior that is exploited here? Maybe some optimism? Do different browsers act differently for this example?

EDIT: I am interested to know about the intent (error or otherwise) of the source code, since x will always be undefined .

+4
source share
3 answers

I think you understand the rise, but here is an explanation of how the function technically looks:

 function module() { function func() { //... definedAfter(); //... } function definedAfter() { //... console.log(x); //outputs undefined //... } var x; return func; x = "...."; } 

(I’m not sure about the actual final order of things raised, but I don’t think it matters)

So, the final line is x = "...."; will never be executed, but x will be declared (as undefined ) and will be accessible by internal function areas.

So I have to say that there is a “mistake” in the library in the sense that the line that sets x as “....” will never be reached and will do nothing.

+3
source

According to Benn Flynn's comment, the parser pre-scans and / or compiles the code before actually executing it. Therefore, it detects the scope of the variable from any line, executed or not, in your block.

Run this in your browser console:

 var f = function() { // we haven't defined a local x yet, so we're tempted to think // that this line is mucking with window.x x = 1; console.log(x, window.x); return; // and we're tempted to think this line is never seen, because it // occurs after the return. but, it ensures that x is local, not global. var x = 2; }; f(); 

In the console, you will see something like this:

 1 undefined 

And then window.x does not exist. It is not mentioned anywhere, thanks to our declaration - whether a part of the declaration is needed, I'm not sure. It should not be. But I won’t be surprised to find out that some version of IE ignores the declaration if the destination is also not present.

Compare this to this:

 var f = function() { x = 1; console.log(x, window.x); return; x = 2; // this line truly does nothing. }; f(); 

We see this in the console:

 1 1 

And after that windows.x has 1 .

It is also noteworthy that definedAfter() works correctly because it is not written in the form of a variable assignment:

 // this puts definedAfter in scope, but it undefined unless this line is // actually executed var definedAfter = function() { /* whatever */ } 

Instead, it is written in the form of a “declarative function” that fails to be “executed”.

 function definedAfter() { /* whatever */ } 

Rather, the compiler sees this at compile time and says, “Oh, this function is part of the scope.” This difference gives you the ability to precisely control when your functions are available in the variable assignment syntax. And in a declarative form, the ability to define your functions anywhere without worrying about the execution order.

+1
source

No, this is not a mistake in the library. However, this is not the most elegant code.

There are two things you need to know to better understand them.

1) The value of the lift 2) the difference between function expressions and function declarations is subtle and yes, different browsers act differently.

(for the latter see http://kangax.imtqy.com/nfe )

amuses

0
source

All Articles