18

In Javascript, when is a new scope created? The 2 situations I know of are:

  1. with a new function (update on 2012/09, I think it needs to be a function invocation, not just a function definition)
  2. in a "with" statement

as a note, any new block (in if-then-else, loops, or just beginning a block for no other reason) won't create a new scope.

Is there a third situation where a new scope is created besides the two situations above? Thanks.

nonopolarity
  • 146,324
  • 131
  • 460
  • 740
  • 1
    EcmaScript 5 strict mode no longer supports the with statement. – fpmurphy Apr 28 '10 at 15:50
  • 3
    Jian Lin, it's customary to accept answer's to your questions. Not so much for the answerer's rep, but so that the rest of the interested community knows that a conclusion was reached. – Justin Johnson Apr 30 '10 at 22:56
  • re definition vs. invokation: I believe scope is a property of the function. When the function is called, a context is created to hold the values for the variables in the function's scope. – allyourcode Sep 12 '12 at 21:09

3 Answers3

9

Yes, there is a third case where the scope chain is augmented (besides the let mozilla-extension that Shog9 mentions), when a catch block is evaluated:

The production Catch : catch (Identifier ) Block is evaluated as follows:

  1. Let C be the parameter that has been passed to this production.

  2. Create a new object as if by the expression new Object().

  3. Create a property in the object Result(2). The property's name is Identifier, valueisC. value, and attributes are { DontDelete }.

  4. Add Result(2) to the front of the scope chain.

  5. Evaluate Block.

  6. Remove Result(2) from the front of the scope chain.

  7. Return Result(5).

So basically, a new object is created, with a property named like the Identifier passed to catch, this new object is added to the scope chain, so we are able to use that identifier within the catch block.

try {
  throw "error";
} catch (identifier) {
  // `identifier` accessible here..
}

But keep in mind that it only augments the current scope temporarily, to introduce the catch Identifier, any variable declared inside will be simply hoisted to the top of it enclosing function.

Community
  • 1
  • 1
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • Excellent, had never given catch evaluation a second thought before reading this! – Shog9 Apr 28 '10 at 15:46
  • In older versions of Firefox, you could actually get ahold of the newly created scope object! `function getScope() { try { throw function () { return this; }; } catch (f) { return f(); } }` Usually when a function using `this` was called without being a method, it would return the global object. But the implementers read "as though by the expression new Object()" literally and implemented it as an object inheriting from the previous scope. Once you got a scope object, you could walk up the prototype chain to get to the others. – Mike Stay Mar 24 '21 at 16:36
6

There's also the let statement. Keep in mind that let (...) {}, like with (...){}, does not create a new scope for variables introduced within the block. However, let definitions can create variables scoped to the block (any block) they're defined in.

Fair warning: as has been pointed out in comments, while let is part of JavaScript 1.7 (the Mozilla dialect of ECMA-262/ECMAScript), it is not part of ECMAScript, and will likely not work any time soon in browsers other than Firefox. Also note that while with can be used as a stand-in for let statements in current implementations of ECMAScript, the "strict" mode proposed for the pending ECMA-262 5th edition disallows this as well. If you're concerned about writing cross-plaform, future-proof code (and you should be...) then stick with functions for scope control!

Community
  • 1
  • 1
Shog9
  • 156,901
  • 35
  • 231
  • 235
  • So tempted to +1 because you're right, but this might cause a bit of confusion since it's not widely implemented yet. Oh... what the heck, you earned it! – Andy E Apr 28 '10 at 15:42
  • 2
    @Andy, is not widely implemented because it is a *Mozilla Extension* available only on SpiderMonkey and Rhino engines, and is not part of the ECMAScript Standard. – Christian C. Salvadó Apr 28 '10 at 15:53
  • @CMS, yes. I (admittedly, mistakenly) wrote *yet* because `let` was part of the intended ECMAScript 4 spec that never came to be and my brain tends to lean toward the fact that it may return in a future update to the standard. – Andy E Apr 28 '10 at 16:41
  • @Andy, Yes, I also think that `let` will be part of *ECMAScript Harmony*, the next step... – Christian C. Salvadó Apr 28 '10 at 17:02
-3

this will also refer to the object you are in:

a = {
   f: function(){ ... },
   b: function(){this.f()}
}
a.b() //calls a.f
Henrik Hansen
  • 2,180
  • 1
  • 14
  • 19