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?
The "use strict" Directive The purpose of "use strict" is to indicate that the code should be executed in "strict mode". With strict mode, you can not, for example, use undeclared variables. The numbers in the table specify the first browser version that fully supports the directive.
Also, note that “use strict” has global scope when written at the beginning of the code while it will have a local scope if written inside a function body.
First, strict mode eliminates some JavaScript silent errors by changing them to throw errors. Second, strict mode fixes mistakes that make it difficult for JavaScript engines to perform optimizations: strict mode code can sometimes be made to run faster than identical code that's not strict mode.
Strict mode changes some previously-accepted mistakes into errors. JavaScript was designed to be easy for novice developers, and sometimes it gives operations which should be errors non-error semantics. Sometimes this fixes the immediate problem, but sometimes this creates worse problems in the future.
"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.)
EDIT It appears I was incorrect. Please see Jeff Walden's answer below.
Check out this answer to a related question: What does "use strict" do in JavaScript, and what is the reasoning behind it?
Despite JSLint's complaints, you can (and should) use "use strict";
inside of a function if you only want that function to be in strict mode. If you use it in the global context then it will force all your code to be in strict mode. Short answer: yes, it will block your use of eval
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With