Preserving the scope in TypeScript

Preserving the scope in TypeScript

Every JavaScript developer had to deal at some point with the issue of referencing Lexical Scope (also called Static Scope).
A common issue is when handling events and how “this” changes”. One of the most important concepts is how scope binds to “this” .

A common workaround this problem in javascript is preserving the scope in a separate variable like in the example below using “that” .

document.getElementById('element').addEventListener('click', function() {
            // this is a reference to the element clicked on
            var that = this;
            $('.elements').each(function() {
                // this is a reference to the current element in the loop
                // that is still a reference to the element clicked on
            });
}

However
while that might be a good solution in javascript there are better ways to fix this in typescript.
And we are going to go over 3 popular solutions.

Option 1) <

class Testing {

    // Define the method signature here.
    doConcreteWork: () = > void;

    constructor() {
        // Implement the method using the fat arrow syntax,
        // which is available since ES6.
        this.doConcreteWork = () = > {
            // Perform your logic to do specific job.
            // Reference `this` as needed.
        }
    }
}

Option 2)
This is commonly referred as the preferred way of solving this problem. If you want to keep your constructor minimal then you can just keep the doConcreteWork method in the class definition and just assign a proxy function in the constructor:

class Testing {

    // Again, define the method signature here.
    doConcreteWorkProxy: () = > void;

    constructor() {
        // Assign the method implementation here.
        this.doConcreteWorkProxy = () = > {
            this.doConcreteWork.apply(this, arguments);
        }
    }

    doConcreteWork(): void {
        // ... doConcreteWorklogic here.
    }

}

Option 3)
Which is still pretty cool is:

class Testing {
    // Define the method signature here.
    doConcreteWorkProxy: () = > void;

    constructor() {
        // Use jQuery to bind doConcreteWorkto this instance.
        this.doConcreteWorkProxy = $.proxy(this.doConcreteWork, this);
    }

    doConcreteWork(): void {
        // ... doConcreteWork logic here.
    }
}

The reason I like this one is because it can be very clean
For example when I use the fabrics class to load image:

class BackgroundProjector {
    private image: fabric.IImage;
    constructor() {
        fabric.Image.fromURL("../test.jpg", $.proxy(this.onLoaded, this));
    }

    onLoaded(img: fabric.IImage) {
        this.image = img;
    }
}

Leave a Comment

Your email address will not be published. Required fields are marked *