Change to Function-Scoped Strict Mode

When strict mode was introduced in ECMAScript 5, the language was quite a bit simpler than it became in ECMAScript 6. Despite that, ECMAScript 6 still allowed you to specify strict mode using the "use strict" directive either in the global scope (which would make all code run in strict mode) or in a function scope (so only the function would run in strict mode). The latter ended up being a problem in ECMAScript 6 due to the more complex ways that parameters could be defined, specifically, with destructuring and default parameter values. To understand the problem, consider the following code:

  1. function doSomething(first = this) {
  2. "use strict";
  3. return first;
  4. }

Here, the named parameter first is assigned a default value of this. What would you expect the value of first to be? The ECMAScript 6 specification instructed JavaScript engines to treat the parameters as being run in strict mode in this case, so this should be equal to undefined. However, implementing parameters running in strict mode when "use strict" is present inside the function turned out to be quite difficult because parameter default values can be functions as well. This difficulty led to most JavaScript engines not implementing this feature (so this would be equal to the global object).

As a result of the implementation difficulty, ECMAScript 2016 makes it illegal to have a "use strict" directive inside of a function whose parameters are either destructured or have default values. Only simple parameter lists, those that don’t contain destructuring or default values, are allowed when "use strict" is present in the body of a function. Here are some examples:

  1. // okay - using simple parameter list
  2. function okay(first, second) {
  3. "use strict";
  4. return first;
  5. }
  6. // syntax error
  7. function notOkay1(first, second=first) {
  8. "use strict";
  9. return first;
  10. }
  11. // syntax error
  12. function notOkay2({ first, second }) {
  13. "use strict";
  14. return first;
  15. }

You can still use "use strict" with simple parameter lists, which is why okay() works as you would expect (the same as it would in ECMAScript 5). The notOkay1() function is a syntax error because you can no longer use "use strict" in functions with default parameter values. Similarly, the notOkay2() function is a syntax error because you can’t use "use strict" in a function with destructured parameters.

Overall, this change removes both a point of confusion for JavaScript developers and an implementation problem for JavaScript engines.