简体   繁体   中英

Weird behaviour with abstract method TypeScript

I use typescript with the reference "atmosphere.d.ts" source here . I trigged a strange behaviour with abstract methods which leads to the error :

TypeError: this.protectedMethod is not a function

Here is the typescript code :

/// <reference path="../atmosphere.d.ts" />
import Request = Atmosphere.Request;

abstract class AbstractRequest {

    // The atmosphere request
    protected socket: Request;

    // Here we initialize the socket
    protected init(url: string): void {
        this.socket = {
            url                 : "http://localhost:9000/" + url,
            contentType         : "application/json",
            transport           : "websocket" ,
            fallbackTransport   : "long-polling"
        };

        /* SOME CODE */

        this.socket.onOpen = function(response) {
            this.protectedMethod();
        };
    }

    // Some protected method called in this.socket.onOpen
    protected abstract protectedMethod(): void;
}

class Registration extends AbstractRequest {

    // Implementation of the abstract method
    protected protectedMethod(): void {
        console.log("hello");
    }
}

Without error, the folllowing javascript code is generated :

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var AbstractRequest = (function () {
    function AbstractRequest() {
    }
    // Here we initialize the socket
    AbstractRequest.prototype.init = function (url) {
        this.socket = {
            url: "http://localhost:9000/" + url,
            contentType: "application/json",
            transport: "websocket",
            fallbackTransport: "long-polling"
        };
        /* SOME CODE */
        this.socket.onOpen = function (response) {
            this.protectedMethod();
        };
    };
    return AbstractRequest;
}());
var Registration = (function (_super) {
    __extends(Registration, _super);
    function Registration() {
        _super.apply(this, arguments);
    }
    // Implementation of the abstract method
    Registration.prototype.protectedMethod = function () {
        console.log("hello");
    };
    return Registration;
}(AbstractRequest));
//# sourceMappingURL=test.js.map

I can't call the abstract method (may be non abstract either?) from the "socket" variable when I implement the "onOpen" method. The only workaround I found for now, is to instantiate a global variable

var registration = new Registration();

and then :

this.socket.onOpen = function(response) {
    registration.protectedMethod;
};

With this workaround, I have to define "protectedMethod" public. Is there an explanation to this behaviour, and a workaround/fix? Btw, I use typescript 1.8.10

Thanks,

This is due to the way that this works in JavaScript :

var AbstractRequest = (function () {
    function AbstractRequest() { }
    AbstractRequest.prototype.init = function (url) {
        // ...snip...
        this.socket.onOpen = function (response) {
            this.protectedMethod();
        };
    };
    return AbstractRequest;
}());

When you call new AbstractRequest().socket.onOpen() this will be bound to socket not to new AbstractRequest() ( this points to whatever is on the left of the dot).

You can use an arrow function to work around this. Within arrow functions this is bound to the context it was defined in, not the context it is being run in:

this.socket.onOpen = response => {
    this.protectedMethod();
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM