javascript – Why isn't this available in the callback?

Question:

I create a class for pagination, I use a wrapper for jquery inside it – the Request class. The getRecords method is a callback that hangs on $(window).scroll() , internally it calls the Request class to make a request, inside which onRequest is a success callback that calls $.ajax() . Inside onRequest , this no longer contains a Pagination but an object containing the request data.

export class Pagination{

    constructor (params? :Object){
        //.. more actions
        this.getRecords();
        fn.setOnWindowListener('scroll','pagination',null,(e) => {this.setScrollEvent(e)});
    }

    private setScrollEvent = (e) :void =>{
        let pos = $(e.currentTarget).scrollTop() + this.paginationHeight;
        let height = $(document).height();
        if(pos >= height && !this.doRequest) this.getRecords();
    };

    public getRecords = () :void =>{
        this.doRequest = true;
        //здесь this - ссылка на Pagination
        return new Request({
            url: this.url + this.currentPage,
            type: `GET`,
            dataType: this.requestDataType,
            onRequest: (data) =>{
                //а здесь this превратился в объект $.ajax()
                this.doRequest = false;
                this.currentPage++;
                this.onRecordsLoaded(data);
            }
        }).exec();
    };

}

The question is how to pass this from Pagination to onRequest so that onRequest sv-va are available inside Pagination ?

ps

of course, you can create a variable before new Request() like var _self = this; and onRequest pull it in onRequest , but it will already be a crutch pulling approach used in es5. This is not an option, as I want to do everything beautifully.

pps

So far, I did the transfer of the context in this way, passing this to getRecords ,

public getRecords = (context: Pagination) :void =>{
        context.doRequest = true;
        return new Request({
            url: context.url + context.currentPage,
            type: `GET`,
            dataType: context.requestDataType,
            onRequest: (data) =>{
                context.doRequest = false;
                context.currentPage++;
                context.onRecordsLoaded(context.context, data);
            }
        }).exec();
    };

And in the constructor, in the same way, remember the context of the class from which the Pagination instance was created:

constructor (context :Object, params? :Object){
        this.context = context;

Answer:

callback is a function. When a function is called, its context is set depending on how it was called, and generally does not match the context of the external function.

The easiest way to pass context to a callback function is via a closure and a local variable:

var self = this;
/**/ (data) => {
    // Здесь this изменился - но self осталась прежней!
}

Sometimes this variable is also called that or _this . If you read the code of the libraries used, you should have noticed such a construction.

Another way to bind context is using bind:

/**/ ((data) => {
    // Здесь this изменился - но self осталась прежней!
}).bind(this);

The bind method binds a function to a context, making the internal context independent of how it was called.

If you were writing in javascript or a recent version of typescript, you could also use the arrow functions from the ECMA 2015 standard, which were specially created to solve this problem – but for your version of typescript such a solution is apparently not available. Maybe you just need to update the typescript compiler …

Scroll to Top