5



While looking into ES6 arrow functions' documentation on Mozilla documentation, I got to know that Arrow functions applies all the rules of strict mode, except one as described in the link

  var f = () => { 'use strict'; return this};
    var g = function () { 'use strict'; return this;}

    console.log(f()); //prints Window
    console.log(g()); // prints undefined

    //we can test this in firefox!

But, Babel.jsis transpiling the arrow function code to ES5 code that returns undefined rather than Window(demo link)

"use strict";

setTimeout(function () {
  return undefined;
}, 100);

So, the above snippet is the output from Babel.js. Couldn't it be the below output?

"use strict";

setTimeout(function () {
  return this;
}.bind(Window), 100);

If I am writing ES6, I would expect Window rather than undefined
Is it a bug?
OR, I misunderstood anything?

Navaneeth
  • 2,555
  • 1
  • 18
  • 38
  • Babel puts everything in strict mode. `undefined` looks correct. – elclanrs Jun 08 '15 at 06:39
  • 1
    @elclanrs It is correct from ES5 perspective since code is transpiled to ES5, but in case of arrow function in ES6 it should be `window`. – dfsq Jun 08 '15 at 06:46
  • 2
    @dfsq why should it be window? It would be inheriting `this` from the encapsulating object, which isn't defined; not the global. Or am I wrong in thinking that? – vol7ron Jun 08 '15 at 06:49
  • 1
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode#.22Securing.22_JavaScript – vol7ron Jun 08 '15 at 06:52

2 Answers2

6

tl;dr: Babel assumes every file is a module. Modules are strict by default and their this value is undefined.


This is covered in the Babel FAQ:

Babel assumes that all input code is an ES2015 module. ES2015 modules are implicitly strict mode so this means that top-level this is not window in the browser nor is it exports in node.

If you don't want this behaviour then you have the option of disabling the strict transformer:

$ babel --blacklist strict script.js

require("babel").transform("code", { blacklist: ["strict"] });

PLEASE NOTE: If you do this you're willingly deviating from the spec and this may cause future interop issues.

See the strict transformer docs for more info.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
2

You are correct in principle, as described on MDN. However, Babel always places a 'use strict' at the root scope. In effect you compile the following:

'use strict';
var f = () => { 'use strict'; return this};

In that case strict rules do apply. See the compiled example here. Babel even optimizes away the top-level this as it is guaranteed to be undefined.

lyschoening
  • 18,170
  • 11
  • 44
  • 54
  • That is what I am doubting... I expect the output to be `Window` and writes my code... So, how could it be valid? – Navaneeth Jun 08 '15 at 17:46
  • 3
    @Navaneeth When `'use strict'` is the first statement in a script, the global `this` object becomes undefined [(see here)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode#.22Securing.22_JavaScript). This also applies to other blocks where this inherits from the global scope. Try e.g. `(function() { console.log(this); }) ()` and `(function() { 'use strict'; console.log(this); }) ()`. Since Babel operates entirely in strict mode, its compiler correctly assumes `this` is undefined in the global scope. If you want to access the `window` object, just do it explicitly. – lyschoening Jun 08 '15 at 18:09