can arrow function gets hoisted in a class? (javascript)

Viewed 229

class App {
  constructor() {
    this.canvas = document.createElement('canvas');
    document.body.appendChild(this.canvas);
    this.ctx = this.canvas.getContext('2d');

    this.pixelRatio = window.devicePixelRatio > 1 ? 2 : 1;

    window.addEventListener('resize', this.resize.bind(this), false);
    this.resize();

    window.requestAnimationFrame(this.animate);
  }

  resize() {
    this.stageWidth = document.body.clientWidth;
    this.stageHeight = document.body.clientHeight;
  }

  animate = () => {
    this.test(); // ---> here!
  };

  test = () => {
    console.log('here!');
  };
}

window.onload = () => {
  new App();
};

An arrow function is not hoisted, only regular functions are hoisted. How come, inside animate function, can call this.test? Different behavior of arrow function in a class?

1 Answers

Although arrow functions aren't hoisted, what you have here aren't just arrow functions - you're using class fields here, which are syntax sugar for assigning a value to the instance inside the constructor (at the beginning of the constructor, just after any super calls). Your code is equivalent to:

class App {
  constructor() {
    this.animate = () => {
      this.test(); // ---> here!
    };

    this.test = () => {
      console.log('here!');
    };
    this.canvas = document.createElement('canvas');
    // ...
  }
}

It's not an issue of hoisting.

First this.animate gets a function assigned to it. Then this.test gets a function assigned to it. Then, eventually, after a requestAnimationFrame, this.animate is called.

For a more minimal example of this:

const fn1 = () => {
  fn2();
};
const fn2 = () => {
  console.log('fn2');
};

fn1();

As long as the line that assigns the function to the variable has run before the function gets called, everything should work.

Related