mms27 mms27 - 2 months ago 9
Javascript Question

Babel replaces this with undefined

This code

beforeEach(() => {
this.asd= '123';
this.sdf= '234';
this.dfg= '345';
this.fgh= '456';


has been transpiled by Babel to:

beforeEach(() => {
undefined.asd= '123';
undefined.sdf= '234';
undefined.dfg= '345';
undefined.fgh= '456';


How come?

Answer

Presumably that code is at global scope, in a module (the default for modules is strict mode) or a file that is being evaluated in strict mode (because it has "use strict" or because of Babel's defaults).

The short version: If you're expecting this to be determined by beforeEach when calling your callback, you'll want to use a function function, not an arrow function. Read on for why Babel is transpiling as it is:

The fundamental thing about arrow functions (other than being concise) is that they inherit this from their context (like a variable they close over), instead of having it set by the caller. In strict mode, this at global scope is undefined. So Babel knows, at compile-time, that this within the arrow function will be undefined and optimizes it.

You've said in comments that this is inside another function, but my guess is that it's inside another arrow function, e.g.:

describe(() => {
    beforeEach(() => {
        this.asd= '123';
        // ...
    });
});

Since Babel knows that this is undefined in the describe callback, it also knows that this is undefined in the beforeEach callback.

If you put your code in a loose mode context, or inside a function call where this can't be determined at compile-time, it won't do that. For example, in strict mode your

beforeEach(() => {
  this.asd= '123';
  this.sdf= '234';
  this.dfg= '345';
  this.fgh= '456';
});

does indeed transpile to

'use strict';
beforeEach(function () {
  undefined.asd = '123';
  undefined.sdf = '234';
  undefined.dfg = '345';
  undefined.fgh = '456';
});

but this:

function foo() {
  beforeEach(() => {
    this.asd= '123';
    this.sdf= '234';
    this.dfg= '345';
    this.fgh= '456';
  });
}

transpiles to

'use strict';

function foo() {
  var _this = this;

  beforeEach(function () {
    _this.asd = '123';
    _this.sdf = '234';
    _this.dfg = '345';
    _this.fgh = '456';
  });
}

...because Babel doesn't know how foo will be called, and thus what this will be.