0

I understand that there is global scope, and additionally nestable functional scope. But are there any other types of scopes or closures in Javascript?

While we're on the topic, what's the difference between a scope, and a closure?

wwaawaw
  • 6,867
  • 9
  • 32
  • 42

1 Answers1

2

A closure is a stack of visible scopes. Let's say you have the following code:

var v1;
function a() {
    var v2;
    function b() {
        var v3;
        function c() {
            var v4;
        }
        return c;
    }
    return b();
}
var f = a();

c is a function that has 4 visible scopes: its own scope (where v4 is defined), the b function's scope (where v3 is defined), the a function's scope (where v2 is defined), and the global scope (where v1 is defined). That stack of visible scopes is the closure, and the function is bound to that closure. When the reference to the c function is returned up the call chain, from b to a and finally assigned to f, it carries this closure binding with it, so when you invoke f(), it will have access to all those scopes, even though you're seemingly invoking a function in the global scope. As you see, there are only two kinds of scopes involved — the global scope and the function scope. The main difference is that variables in the global scope are defined as properties of the global object, while function scope vars are not properties of any object and cannot be referenced in any other way but by name. A closure is not a scope in itself, but a collection of scopes.

lanzz
  • 42,060
  • 10
  • 89
  • 98
  • are there other types of scopes but functions and `window`? – wwaawaw Sep 22 '12 at 12:14
  • I've seen instance properties and inherited properties described as "scopes", but they really aren't. Those are the two actual variable scopes in JS. – lanzz Sep 22 '12 at 15:47
  • Accepted -- here's a curveball for you, though. What if I define a function as a member of an object, which then gets passed to an X-origin iframe via `iframeWin.postmessage(objectContainingMemberFunction)`? Would it still carry its closure into the new window? – wwaawaw Sep 29 '12 at 11:52
  • 1
    `postmessage` [serializes](https://developer.mozilla.org/en-US/docs/DOM/The_structured_clone_algorithm) the passed object, and the serialization algorithm cannot serialize functions. Passing that object to `iframeWin.postmessage` will result in a `DATA_CLONE_ERR` exception. – lanzz Sep 29 '12 at 12:06
  • Interesting. What about `iFrameWin.postMessage({f: function(){console.log('foo');}.toString()})`, and then `eval`ing it on the recipient's end? – wwaawaw Sep 29 '12 at 12:48
  • 1
    This would define the function on the recipient's end. Closure binding happens on definition time, so the new function will have the scope visible at the point where it is defined on the recipient's end. – lanzz Sep 29 '12 at 16:29
  • So, aside from the closure not carrying over, it should still work, right? – wwaawaw Sep 29 '12 at 17:19
  • 1
    Yes, of course. `eval`-ing a string that holds code that defines a function will happily define the function, no matter where that string came from. – lanzz Sep 30 '12 at 09:50