In ECMAScript5, what’s the scope of “use strict”?

"use strict" applies only to function or program scope. So if you have fileA.js with "use strict" at the top, fileA.js executes in strict mode, and all functions defined in it will do the same when called. But fileB.js is a separate program, so the "use strict" from fileA.js doesn’t apply to it — and therefore fileB.js will execute in non-strict mode. (Of course, if somecodesnippet begins with a "use strict" directive and parses properly, that code will execute in strict mode, and functions defined by that code will do likewise.) Strictness absolutely does not “bleed” — and per ES5 4.2.2 (admittedly non-normative, but I’m sure I could dig up a normative reference for this if necessary), “an implementation must support the combination of unrestricted and strict mode code units into a single composite program”.

One gotcha of this: if you use strict mode in the global scope sometimes but not always, you can no longer concatenate your scripts into a single file. Suppose you have scripts A, B, C, D in that order. If A is strict, the overall concatenation will be strict, even if B/C/D weren’t! Conversely, if A isn’t strict (and is non-empty), the overall concatenation will be non-strict, even if B/C/D were strict. This has already bitten at least one early-adopter site out there.

All that said, strict mode does not forbid eval. When eval is called the normal way in strict mode, using program syntax of the form eval(code [, ...]), it’s a “direct” eval which behaves the way eval always has — except that code is always evaluated as strict mode code, even if code doesn’t start with a "use strict" directive, and except that any variables created by the code are kept in their own separate storage from any existing variables. (The exact semantics are a bit complicated; I work on Firefox’s JavaScript engine, of late implementing this stuff, and even after a fair amount of time in the spec and working on an implementation it’s still not intuitive to me.)

If it’s not called that way — eval.call(...), setTimeout(eval, ...), setInterval(eval, ...), var ev = eval; ev(...);, and so on — it’s an “indirect” eval. Indirect eval (whether inside or outside strict mode) behaves a little differently: name resolution and variable definition occur as though in the global scope. (The code will execute as strict mode code only if it begins with a "use strict" directive.)

Strict mode support is nearly — but not completely — finished in the latest Firefox nightlies, so it may be worth downloading one to play around with those parts of strict mode which are implemented. I’d still say hold off on production use until it’s complete, but it’s definitely ready for experimentation (so long as you understand strict mode isn’t fully in yet). (As for Sean McMillan’s link, be aware that its claims of “support” represent the extreme minimum of functionality needed for each bullet. The strict mode tests are much better, although to be sure they’re nowhere close to covering strict mode completely.)

Leave a Comment