What scope does the strict mode pragma have in ECMAScript5?
"use strict";
I'd like to do this (mainly because JSLint doesn't complain about it):
"use strict";
(function () {
// my stuff here...
}());
But I'm not sure if that would break other code or not. I know that I can do this, which will scope the pragma to the function...
(function () {
"use strict";
// my stuff here...
}());
but JSLint complains about it (when the "strict" JSLint option is enabled) because it thinks you're executing code before you enable "use strict".
Here's my question. If I have fileA.js:
"use strict";
// do some stuff
and fileB.js:
eval( somecodesnippet ); // disallowed by "use strict"
and then include them in my html page in that same order, will the pragma be scoped to the file, or will the pragma bleed over into fileB, thus blocking the eval execution?
"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.)