1

If a function is declared in the global scope, but defined within a local scope, which scope does it belong to? I ask because I know it has access to the local function's scope (where it is defined in), but the declaration confuses me.

Example:

var funcDef;
function a() {
    var msg = "Hello, world!";
    funcDef = function() {
        return msg;
    }
}
a();
console.log(funcDef()); // prints Hello, world!

My understanding is the variable, funcDef itself is bound to the global scope, and its function declaration is still bound within a()'s scope. Can someone confirm?

ihgann
  • 505
  • 3
  • 11
  • http://en.wikipedia.org/wiki/Closure_%28computer_programming%29 – SLaks Sep 14 '14 at 01:53
  • @PM77-1 I saw that but don't believe it's a duplicate, at least not explicitly. It's under the same topic, but in this case funcDef is declared globally and in the examples there, the function is still always both declared and defined within another function. Effectively, I didn't receive my desired solution from reading it. – ihgann Sep 14 '14 at 02:15
  • You declared `funcDef` globally (not as `var funcdeg`), so it cann't be a surprise that it's visible outside of its outer function. What's really interesting (if you do not know about *closures*) that it's still has access to `msg` which is local to the outer function. So the first part was trivial, another explained in the post I linked to. – PM 77-1 Sep 14 '14 at 02:19
  • The more interesting question here is *why* you would want to define a function such as `a` that has the side-effect of redefining a global variable. This is likely to be poor program design. –  Sep 14 '14 at 03:48
  • @torazaburo This is merely for understanding, not for practice. – ihgann Sep 14 '14 at 04:20

3 Answers3

1

Forget the fact that this is a function and think of it as a variable. Let's say you change the function a (please choose better names next time) to assign a string value to funcDef.

console.log(funcDef); would print undefined before a() is executed and afterwards it would print the string value.

This is similar, the value of funcDef would be undefined until a() is executed, after which it has a function assigned to it.

Of course the above is a simplification of what is really going on, but you can think that way. In actuality, because of closure, msg will be kept around and alive after a() has returned.

Read this article for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

Ameen
  • 2,576
  • 1
  • 14
  • 17
1

function() { return msg; } is just a value for funcDef, like 5, true, and so on, and funcDef is declared within the global scope (therefore visible everywhere).

Functions get access to the execution scope inside which they were created (and to the outer scopes as well). If you would have called a() one more time the value for funcDef would have been a different function with access to a different execution scope (since it was created inside another call of a).

var funcDef;
function a(msg) {
    funcDef = function() {
        return msg;
    }
}

a("foo");
a("bar");
console.log(funcDef()); // bar

Functions are visible within the scope in which they were created.

var funcDef;

function a() {
  function f() { console.log(1); }
  funcDef = f;
}

a();

funcDef(); // works
f(); // fails, not visible

by the way, rule of thumb:
- if the first token of a statement is the keyword function it's a function declaration (therefore it is hoisted to the top); if not it is a function expresion and it behaves like a normal variable declaration.

/* function declaration */

f(); // works

function f() { console.log(1); } 

/* function expression */

g(); // fails

var g = function () { console.log(2); };

/* function expression */

namedFunc(); // fails

var h = function namedFunc() { console.log(1); };
  • Based on what you said, I just want to confirm if I am correct in my understanding then. funcDef, the variable, is still in the global scope (which is why we can access it globally, unlike msg). However, funcDef's value's a function that's declared within the scope of the a() that last called it. – ihgann Sep 14 '14 at 02:12
  • 1
    it is correct, the value for `funcDef` is a function created inside the second call of `a` and in normal conditions it cannot be used outside (here you can because you assign it to a global var) –  Sep 14 '14 at 02:20
1

This is a very good question.

As @AlliterativeAlice said, the scope is intuitive and expected, global.

Now the reason why funcDef knows msg is the most interesting part of it.

Indeed as @Ameen told you, you just applied a closure when you called a().

At that time, funcDef "frozen" its references to parent scope and variables.

So, when you call funcDef, it just had in its scope msg with the Hello, world! value.

Niloct
  • 9,491
  • 3
  • 44
  • 57