views:

608

answers:

6

Hello Javascript experts

Today I had a discussion with a colleague about nested functions in Javascript:

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

In this example, trials point out that b is not reachable outside the body of a, much like c is. However, d is - after executing a(). Looking for the exact definition of this behaviour in the ECMAScript v.3 standard , I didn't find the exact wording I was looking for; what Sec.13 p.71 does not say, is which object the function object created by the function declaration statement is to be bound to. Am I missing something?

+3  A: 

As I understand it, these are equivalent as far as scoping is concerned:

function a() { ... }

and

var a = function() { ... }
eyelidlessness
+14  A: 
keparo
Exactly right -- broadly speaking `function a(){}` is equivalent to `var a = function(){}` (there are some minor semantic differences, but nothing too significant).
olliej
thank you, but where do I find the following assertions in the ECMAScript standard (or is it missing?): "Statements within a function are scoped within that function." In my impression, the semantics of "var a= function(){}" are well-defined, but not those of statement "function a(){...}".
Dong Hoon
The ECMAScript standard will only give you the guidelines for implementing ECMAScript, of which Javascript is just one family member. So you won't find that exact statement, but there are other resources that can help you. See my additional note above.
keparo
A: 

...

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

without being preceded by var, d is global. Do this to made d private:

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   var d = 'Bound to local object.'
}
rp
+1  A: 

It seems important to note that while d is being created as a "global", it is in reality being created as a property of the window object. This means that you could inadvertently be overwriting something that already exists on the window object or your variable might actually fail to be created at all. So:

function a() {
    d = 'Hello World';
}
alert(window.d); // shows 'Hello World'

But you cannot do:

function a() {
    document = 'something';
}

because you cannot overwrite the window.document object.

For all practical purposes you can imaging that all of your code is running in a giant with(window) block.

Prestaul
Yes, this behavior is specified in Sec. 10.1.9 of the ECMAScript standard.
Dong Hoon
A: 

Javascript has two scopes. Global, and functional. If you declare a variable inside a function using the "var" keyword, it will be local to that function, and any inner functions. If you declare a variable outside of a function, it has global scope.

Finally, if you omit the var keyword when first declaring a variable, javascript assumes you wanted a global variable, no matter where you declare it.

So, you're calling function a, and function a is declaring a global variable d.

Alan Storm
A: 

Thank you very much for your extensive explanation, keparo! I did and do understand from both cited sources that within a function body, local variables are bound to the local execution context. However, the semantics of the nested function statement is explicitized nowhere in this regard.

I know that the standard shouldn't say anything about implementations (among which Javascript), though it should be unambiguous about the semantics of all of its elements and constructs.

Thanks also for the pointer to Douglas Crockford's book --- didn't know it.

Dong Hoon