everconfusedGuy
everconfusedGuy

Reputation: 2797

can strict mode be removed without side-effects

I have a JavaScript application and I would like to know if by removing all the "use strict;" statements in the program, I would be changing its behaviour in some way.
As far as I understand, strict mode does not allow some stuff and once the application has finished development, I can remove it without causing any side-effects.
There is also the case of the 'this' variable mentioned here but Chrome does not seem to have implemented this behaviour till now.
Thanks!

Upvotes: 3

Views: 163

Answers (2)

Qantas 94 Heavy
Qantas 94 Heavy

Reputation: 16020

There are a few cases where your code may be affected, though most of them are rather contrived:

  • When passing null or undefined as the this value (in non-strict mode this is converted to the global object, not an empty object):

    'use strict';
    (function () {
        if (!this) console.log('performs proper actions');
        else console.log('fail! oops...');
    }).call(undefined); // 'performs proper actions'
    

    In strict mode, this would log "performs proper actions". However, this isn't the same in non-strict mode, where you'd get the failure message:

    (function () {
        if (!this) console.log('performs proper actions');
        else console.log('fail! oops...');
    }).call(undefined); // 'fail! oops...'
    

    It also has the same behaviour if you use null instead of undefined.

  • If your function relies on the this value not being coerced to an object -- in non-strict mode, this is implicitly coerced to an object. For example, values such as false, 'Hello World!', NaN, Infinity and 1 will be coerced to their object wrapper equivalents (as mentioned before, null and undefined have their own behaviour). Compare what happens in strict mode:

    'use strict';
    (function () { console.log(this); }).call(1); // 1
    

    ... with what happens in non-strict mode:

    (function () { console.log(this); }).call(1); // '[object Number]'
    
  • When relying on formal parameters and the arguments object not sharing their values on assignment:

    function strict(a, b, c) {
        'use strict';
        var a = 1;
        var b = 2;
        var c = 3;
        var d = 4;
        console.log('strict: ' + (arguments[0] === a ? 'same' : 'different')); // different
        console.log('strict: ' + (arguments[1] === b ? 'same' : 'different')); // different
        console.log('strict: ' + (arguments[2] === c ? 'same' : 'different')); // different
        console.log('strict: ' + (arguments[3] === d ? 'same' : 'different')); // of course they're different; by design
    }
    
    function notStrict(a, b, c) {
        var a = 1;
        var b = 2;
        var c = 3;
        var d = 4;
        console.log('non-strict: ' + (arguments[0] === a ? 'same' : 'different')); // same
        console.log('non-strict: ' + (arguments[1] === b ? 'same' : 'different')); // same
        console.log('non-strict: ' + (arguments[2] === c ? 'same' : 'different')); // same
        console.log('non-strict: ' + (arguments[3] === d ? 'same' : 'different')); // of course they're different; by design
    }
    
    strict(0, 1, 2, 3);
    notStrict(0, 1, 2, 3);
    

    What you get is the following:

    strict: different
    strict: different
    strict: different
    strict: different
    non-strict: same
    non-strict: same
    non-strict: same
    non-strict: different
    
  • If you have been using eval and you call it directly, you'll find that variables and functions declared inside the eval call are leaked to the surrounding scope, instead of being in its own scope when in strict mode. For example, a retains its original value in strict mode:

    'use strict';
    var a = 42;
    eval('var a = -Infinity;');
    console.log(a); // 42
    

    ... while in non-strict mode, it is assigned a new value:

    var a = 42;
    eval('var a = -Infinity;');
    console.log(a); // -Infinity
    

    If you were relying on a new scope being created, this would be a breaking change to your code.

  • If you deliberately use the way that a ReferenceError is thrown if you attempt to assign to a variable that has not been defined yet, this will affect the way your code runs:

    try {
        randomVariableThatHasntBeenDefined = 1;
    } catch (e) {
        alert('performs logic');
    }
    

    The alert will not be shown in non-strict mode.

All of these can be found in Annex C of the ECMAScript 5.1 Specification, which is the authoritative reference for what happens in each of these cases. While it isn't exactly easy reading, it can be useful to understand particular corner cases and why they behave as they do.

Upvotes: 2

Guffa
Guffa

Reputation: 700372

In most cases strict mode just limits what the code can do, but you can't assume that removing strict mode never changes the behaviour. The use of the arguments array is for example different in strict mode and normal mode.

Example:

function test(a) {
  "strict mode";
  a = 42;
  return arguments[0];
}

If you call this function with test (1337) it will return 1337, but if you remove the strict mode from it, it would instead return 42.

For a comprehensive list of what the strict mode does: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode

Upvotes: 1

Related Questions