28

Similar, but not the same as, How to enable ECMAScript "use strict" globally?

I have bought JavaScript Patterns and it recommends enabling use strict. Adding it to the two dozen javascript files would be a bit of a chore, so enabling it globally would be nice. I originally thought about adding to the top of my main.js like this:

"use strict" 
require({
    priority: ["jquery", "raphael", "myapp"] 
});

However I then thought that it maybe would only enable it for that file. I then thought about this:

<script data-main="lib/main" src="lib/require.js">"use strict"</script>

Would either of these enable ECMAScript 5 strict mode globally?

Community
  • 1
  • 1
graham.reeds
  • 15,267
  • 16
  • 66
  • 133

3 Answers3

43

TL;DR:

No, a "use strict" in one script element does not impose "use strict" on code in other script elements. It applies only to the source text it's part of.

(Separately, re the script tag at the end of the question: If a script element has a src, any inline text it has is considered "documentation" and is ignored.)


Update:

It's clearer in the specification now (maybe it was clear in ES5, but just not to me) that yes, separate script elements are separate for the purposes of "use strict". The quote below in the original answer has been changed slightly to say "source text" rather than "code unit", and the Scripts and Modules section goes into more detail.


Original answer:

The specification says:

Because strict mode is selected at the level of a syntactic code unit, strict mode only imposes restrictions that have local effect within such a code unit. Strict mode does not restrict or modify any aspect of the ECMAScript semantics that must operate consistently across multiple code units.

(Section 4.2.2)

So the question is: Are different script tags different syntactic code units?

V8 (the JavaScript engine inside Chrome) appears to believe that they are separate and so putting a single "use strict"; in global scope at the top of your page would not work. Perhaps it's specified somewhere I haven't found yet, but in any case, it's a reasonable interpretation.

Assuming no declaration for foo that isn't shown, this code falls prey to The Horror of Implicit Globals in normal mode:

function test() {
    try {
      foo = "bar";
      display("foo = " + foo);
    }
    catch (e) {
      display("Exception: " + e);
    }
}

In normal mode, that creates a new global variable foo with the value "bar" and shows the "foo = bar" message. In strict mode, an exception is thrown because foo is undefined.

If I put this script tag in a page:

<script>
"use strict";
function test() {
    try {
      foo = "bar";
      display("foo = " + foo);
    }
    catch (e) {
      display("Exception: " + e);
    }
}
</script>

...I get the exception as expected (live example). If I put them in separate script tags, though:

<script>
"use strict";
</script>
<script>
function test() {
    try {
      foo = "bar";
      display("foo = " + foo);
    }
    catch (e) {
      display("Exception: " + e);
    }
}
</script>

I don't get the exception (on V8) (example). And that's reasonable if you think about how the browser and the JavaScript engine are interacting.

And similarly, if the function is off in another file and I do this:

<script>
"use strict";
</script>
<script src="/inatoq"></script>

I don't get the exception (example), presumably for the same reason.

Note that your example tag here:

<script data-main="lib/main" src="lib/require.js">"use strict"</script>

is invalid. A script tag may either have a src attribute or content, but not both. (Well, basically; details here [HTML5] and here [HTML 4.01].) If it has a src element, the browser is supposed to disregard the content, and most do. Most. :-)

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • The book does mention globally in it's description but gives no example of how to do that. So I guess I have to have it at the start of every module. I thought because placing it in the main it might 'cascade' down the modules loaded by require.js. I suppose implicitly declaring it in every file means I can easily disable it for modules that break any strict rules. – graham.reeds Jun 27 '11 at 08:34
  • If you follow the Amazon link I included above you can look inside the book and it is on page 5. – graham.reeds Jun 28 '11 at 08:31
  • 3
    I think it is important to mention that syntactic code units are often combined into a single file and then minified for production code. This basically applies strict mode globally since it is now a single syntactic code unit. This needs to be kept in mind and is the reason tools like JSLint do not like `"use strict";` outside of closures. – jwueller Feb 09 '13 at 14:05
8

JSLint is suddenly reporting: Use the function form of "use strict"

(function () {
    "use strict";
    // put all of your strict code here


}());
Community
  • 1
  • 1
Jeremy Bell
  • 688
  • 5
  • 9
6

no, script tags are considered programs and are therefor code units. "use strict" should not carry over from one script tag to another.

Each script tag is interpreted individually and actually have their own scope. This scope is not noticable since everything declared globally will end up on the global object, but it's there nontheless. The string "use strict" will be garbage collected at the end of the program/script tag as it has no pointer/reference.

BGerrissen
  • 19,774
  • 3
  • 36
  • 40
  • 3
    Do you have any references for the above? Clearly there is a mechanism at work, though I wouldn't say *"Each script tag...actually have their own scope."* because if they literally did (their own execution context) that would mess up `var` and function declarations. But clearly there's something, and I'd like to understand it better if you can point me at anything. Thanks, – T.J. Crowder Jun 27 '11 at 08:57
  • What T.J. said. This answer is the sort of thing that requires citation. How is it a different scope from one tag to the other if, as you say, the global scope all ends up on the global object? Every explanation of JS engines I've heard has anything not inside a function being called an LHS reference to the scope of global...no distinction made for different scope for different script tags. It may be the case that there is some sort of different scope that affects some things like strict mode, not ruling it out, but since the claim is counter to many things we see it needs some sort of cite. – Jimbo Jonny Dec 31 '15 at 15:54
  • @JimboJonny: FYI, recent specs are clearer on this (at least to me), I've added more recent links to the top of [my answer](http://stackoverflow.com/a/6483866/157247). I mean, we all knew it worked this way, but... – T.J. Crowder Apr 21 '17 at 09:02