views:

206

answers:

2

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?

A: 

Check out this answer to a related question: http://stackoverflow.com/questions/1335851/what-does-use-strict-do-in-javascript-and-what-is-the-reasoning-behind-it/1335881#1335881

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.

ntownsend
I'll go farther. You should not use `"use strict"` unless you have a way to test with it. Since no browser yet supports it (http://kangax.github.com/es5-compat-table/), it would be better to leave it out. Putting it in to make jslint happy will make you unhappy once it gets really supported and your code breaks.
Sean McMillan
A: 

"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, and regarding strict mode in particular it tests only a single requirement of strict mode -- there's lots of other parts that make strict mode far more complicated than the single facet the page chooses to test.)

Jeff Walden