4
function f() { return s; } // works fine though no `s` is defined yet !

var s=1;
f(); // 1

delete s;

var s=2;
f(); // 2 

(function() {
var s=3;
f(); // 2 and not 3 which means lexical scoping is at play (?)
})();

first off, you can close over a variable (s) which is not yet defined. How is that possible if lexical (static) scoping is used?

second, after deleting the original s, f() can find the new s. Does this mean closures are bound to variable names rather than references or symbol table indexes or something more machine-level? I would expect from e lexical scoping closure to throw an error since the original sis deleted. The new s just reuses the name and has nothing to do with the original s.

And third, the s inside the anonymous function scope is not used by f(), does this mean indeed lexical scoping is at play?

Hardik Shah
  • 4,042
  • 2
  • 20
  • 41
Ashkan Kh. Nazary
  • 21,844
  • 13
  • 44
  • 68
  • 1
    I guess we can answer any "closure" question with "hoisting" without even reading them. – georg Mar 29 '13 at 14:52
  • You might find it instructive to try two variations: first, put that code in an IIFE - `(function() { ...code... })();`. Then, try your original code except with the statement `"use strict";` (just that string constant) at the very top. – Pointy Mar 29 '13 at 14:54
  • (Actually the `"use strict";` modification is probably the most interesting.) Anyway yes, it's all about lexical scoping. – Pointy Mar 29 '13 at 14:56
  • oops actually in strict mode the `delete` statement just won't work at all. – Pointy Mar 29 '13 at 15:02

2 Answers2

3

first off, you can close over a variable (s) which is not yet defined ... how is that possible if lexical (static) scoping is used ?

Refer hoisting

second, after deleting the original s, f() can find the new s. Does this mean closures are bound to variable names rather than references or symbol table indexes or something more machine-level? I would expect from e lexical scoping closure to throw an error since the original s is delete. The new s just reuses the name and has nothing to do with the original s.

There is no new s, all declarations are hoisted. There is only one s in the end. Hoisting still applies.

and third, the s inside the anonymous function scope is not used by f(), does this mean indeed lexical scoping is at play ?

Yes, the s inside the anonymous function is local to it, and in this case the closure formed over the global s.

Johnbabu Koppolu
  • 3,212
  • 2
  • 22
  • 34
  • I think the "second" is actually due to `delete s` having no effects and not the hoisting as demonstrated in http://jsfiddle.net/F5xDz/ – Ashkan Kh. Nazary Mar 29 '13 at 15:21
2

This example is equivalent to

var s;
function f() { return s; } // works fine though no `s` is defined yet !

s=1;
f(); // 1

delete s;

s=2;
f(); // 2 

(function() {
var s=3;
f(); // 2 and not 3 which means lexical scoping is at play (?)
})();

Javascript variable declarations are hoisted to the top of their scope and are declared then. They're then defined where the user sets them to be. So you can reference a javascript variable before its declared in a function scope.

Also note that delete is generally used for properties on an object, not an object declared with var. Delete in this case has no effect, regardless of closure. See fiddle here: jsfiddle

Ben McCormick
  • 25,260
  • 12
  • 52
  • 71