Javascript Strict Mode

by Dmitrey Gerasimov

What is it?

Before

After

Browser Support

'use strict'

Applies to

  • entire scripts
  • individual functions

No block scope

Strict for scripts

// Put it before any statement
'use strict';
var v = "Strict is watching you";

Caution

Strict for functions

function strict() {
  // Also put it before any statement (of function)
  'use strict';
  function nested() { return "And so am I!"; }
  return "I'm strict!" + nested();
}
function notStrict() { return "I'm not strict."; }

Difference

Exposing hidden "enemies"

unexpected globals

'use strict';
// Some code withouy any vars
answer = 42; // throws a ReferenceError

bending unbendable

'use strict';

// Assignment to a non-writable property
var obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9; // throws a TypeError

// Assignment to a getter-only property
var obj2 = { get x() { return 17; } };
obj2.x = 5; // throws a TypeError

bending unbendable

// Assignment to a new property on a non-extensible object
var fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // throws a TypeError

// Assignment to NaN
NaN = 'not NaN';

// Delete undeletable
delete Object.prototype; // throws a TypeError

No clones in my republic

'use strict';
var o = { p: 1, p: 2 }; // !!! syntax error
function sum(a, a, c){ // !!! syntax error
  'use strict';
  return a + b + c; // wrong if this code ran
}

052

'use strict';
var sum = 030 + 022; // Syntax error;

Simplifying yours and compiler's life

without 'with'

'use strict';
var x = 42;
with (obj) // Syntax error
{
  x;
}

evil

var x = 17;
var evilX = eval("'use strict'; var x = 42; x");
assert(x === 17);
assert(evalX === 42);
example

Even more evil

function strict1(str){
  'use strict';
  return eval(str); // str will be treated as strict mode code
}
function strict2(f, str){
  'use strict';
  return f(str); // str is strict if and only if it invokes strict mode
}
function nonstrict(str){
  return eval(str); // str is strict if and only if it invokes strict mode
}

plain names

'use strict';
var x;
delete x; // Syntax error
example

Evil arguments

'use strict';
eval = 42;
arguments++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function("arguments", "'use strict'; return 42;");

no aliases

function f(a){
  'use strict';
  a = 42;
  return [a, arguments[0]];
}
var pair = f(17);
assert(pair[0] === 42);
assert(pair[1] === 17);

function callee

'use strict';
var f = function() { return arguments.callee; };
f(); // throws a TypeError

Securing your code

this is always as is

'use strict';
function fun() { return this; }
assert(fun() === undefined);
assert(fun.call(2) === 2);
assert(fun.apply(null) === null);
assert(fun.call(undefined) === undefined);
assert(fun.bind(true)() === true);
example

no stackwalker

unction restricted()
{
  'use strict';
  restricted.caller;    // throws a TypeError
  restricted.arguments; // throws a TypeError
}
function privilegedInvoker()
{
  return restricted();
}
privilegedInvoker();

r.i.p. Caller

'use strict';
function fun(a, b)
{
  'use strict';
  var v = 12;
  return arguments.caller; // throws a TypeError
}
fun(1, 2); // doesn't expose v (or a or b)

Building future

restricted words

function package(protected){ // !!!
  'use strict';
  var implements; // !!!

  interface: // !!!
  while (true){
    break interface; // !!!
  }

  function private() { } // !!!
}
function fun(static) { 'use strict'; } // !!!

not kosher

'use strict';
if (true){
  function f() { } // !!! syntax error
  f();
}

for (var i = 0; i < 5; i++){
  function f2() { } // !!! syntax error
  f2();
}

function baz(){
  function eit() { }
}

don't rely on it

Thank you