Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript "this" instance is undefined in class

I found this and online and now trying to put it in TS.

Running the following throws Uncaught TypeError: Cannot set property 'toggle' of null

@Injectable()
export class HomeUtils {
    private canvas: HTMLCanvasElement;
    private context;
    private toggle = true;

    constructor() { }

    public startNoise(canvas: HTMLCanvasElement) {
        this.canvas = canvas;
        this.context = canvas.getContext('2d');
        this.resize();
        this.loop();
    }

    private resize() {
        this.canvas.width = window.innerWidth;
        this.canvas.height = window.innerHeight;
    }

    private loop() {
        this.toggle = false;
        if (this.toggle) {
            requestAnimationFrame(this.loop);
            return;
        }
        this.noise();
        requestAnimationFrame(this.loop);
    }

    private noise() {
        const w = this.context.canvas.width;
        const h = this.context.canvas.height;
        const idata = this.context.createImageData(w, h);
        const buffer32 = new Uint32Array(idata.data.buffer);
        const len = buffer32.length;
        let i = 0;

        for (; i < len;) {
            buffer32[i++] = ((255 * Math.random()) | 0) << 24;
        }

        this.context.putImageData(idata, 0, 0);
    }

}

I'm lost.

like image 660
Relm Avatar asked Mar 16 '18 11:03

Relm


People also ask

Why this in TypeScript is undefined?

A variable is undefined when it's not assigned any value after being declared. Null refers to a value that is either empty or doesn't exist. null means no value. To make a variable null we must assign null value to it as by default in typescript unassigned values are termed undefined.

How do you know if a property is undefined TypeScript?

To check for undefined in TypeScript, use a comparison to check if the value is equal or is not equal to undefined , e.g. if (myValue === undefined) {} or if (myValue !== undefined) {} . If the condition is met, the if block will run.

Is null in TypeScript?

TypeScript has a powerful system to deal with null or undefined values. By default null and undefined handling is disabled, and can be enabled by setting strictNullChecks to true.

How do you use this in TypeScript?

The "this" keyword always points to the object that is calling a particular method. The type of "this" in an expression depends on the location in which the reference occurs: In a constructor, member function, or member accessor, this is of the class instance type of the containing class.


2 Answers

Methods do not capture this and are dependent on the caller to call them with the correct this. So for example:

this.loop() // ok
let fn = this.loop;
fn(); // Incorect this
fn.apply(undefined) // Undefined this

Since you pass loop to another function requestAnimationFrame you need to ensure that this is captured from the declaration context and not decided by requestAnimationFrame :

You can either pass an arrow function to requestAnimationFrame

private loop() {
    this.toggle = false;
    if (this.toggle) {
        requestAnimationFrame(() => this.loop());
        return;
    }
    this.noise();
    requestAnimationFrame(() => this.loop());
} 

Or you can make loop an arrow function not a method:

private loop = () => {
    this.toggle = false;
    if (this.toggle) {
        requestAnimationFrame(this.loop);
        return;
    }
    this.noise();
    requestAnimationFrame(this.loop);
}

The second approach has the advantage of not creating a new function instance on each call to requestAnimationFrame, since this will be called a lot, you might want to go with the second version to minimize memory allocations.

like image 121
Titian Cernicova-Dragomir Avatar answered Sep 30 '22 21:09

Titian Cernicova-Dragomir


It's the call to requestAnimationFrame. You are passing a function not bound to a context, and so, inside that call to loop there is no this.

Change the call to:

requestAnimationFrame(() => this.loop());

Arrow functions, contrarily to normal functions, are bound to this.

like image 34
Oscar Paz Avatar answered Sep 29 '22 21:09

Oscar Paz