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

1

6

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?

Jehu answered 30/12, 2020 at 17:34 Comment(0)
S
7

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.

Study answered 30/12, 2020 at 17:36 Comment(4)
``` videoElem.addEventListener('canplaythrough', render); const render = () => { ctx.drawImage(videoElem, 0, 0, 600, 400); ctx.font = '20px Bungee Outline'; ctx.fillStyle = 'white'; } ``` in this case, i got an error - then why is that?Jehu
@Jehu Because, as CertainPerformance explained, arrow functions aren't hoisted (in the sense you mean), and what you see in the class is a different thing. However, this example has no class in it at all, so even if they may look similarly, they're different. For this example, refer to TDZ (Temporal Dead Zone)Cardie
@Study If I'm right, the problem with the code in facVV's comment is that the render variable (that contains an arrow function) is referenced earlier than it's defined...Cardie
@Jehu You can't run a line that references a variable before the line that has initialized the line (with const someVarName =) has run.Study

© 2022 - 2024 — McMap. All rights reserved.