最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Typescript event handler function for event type field - Incorrect context - Stack Overflow

programmeradmin1浏览0评论

This is a jquery interface from jquery.d.ts:

export interface IDialogEvent extends DialogEvent {
    (event: Event, ui: DialogUIParams): void;
}

This is my custom interface mimicking partial functionality of the DialogOptions interface of jquery.d.ts:

export interface IDialogOptions {
    open: IDialogEvent;
}

export class DialogClass implements IDialogOptions { 

    //Dialog options
    public open: IDialogEvent;

    //Class related fields
    public someField: any;
    public dialogEl: JQuery;

    constructor() { 
        this.open = this.OpenHandler;
        this.dialogEl = $("<div></div>").dialog(this); 
        //Passing "this" initializes the dialog by mapping relevant class fields
        //to the dialog's "option" object, in this case the only "relevant" field is "open".
    }

    public OpenHandler(event: Event, ui: DialogUIParams) { 
        var value = this.someField; //BAD. "this" is not type BaseClass
    }

    public NonEventHandlerMethod() { 
        var value = this.someField; //GOOD. "this" is type BaseClass
    }  
}

var dialog = new DialogClass();
dialog.dialogEl.dialog("open"); 

The last line fires OpenHandler() but inside it, this is not type BaseDialog (unlike in NonEventHandlerMethod).

The reason I need an event handler function for the dialog options field and the reason why I can't simply do this:

 export class DialogClass implements IDialogOptions { 
     ...
      constructor() { 
          this.open = () => {
                //event handling logic
          };
          ...
      }
      ...
 }        

is because I need to add additional open-event handling logic in classes that extend DialogClass and there is no differentiation between this.member and super.member... there is only differentiation between this.function() and super.function():

 export class LoginDialog extends DialogClass { 
     ...
      constructor() { 
          this.open = this.OpenHandler;
          ...
      }

      public OpenHandler(event: Event, ui: DialogUIParams) { 
           super.OpenHandler(); //Base handling logic

           //Additional handling logic
      } 
      ...
 } 

I think this may be a bug because

   export class DialogClass implements IDialogOptions { 
     ...
      constructor() { 
          this.open = () => {
                var test = this.someField;  //Correct context
          };
          ...
      }
      ...
   }  

and calling the method directly:

   var dialog = new DialogClass();
   dialog.OpenHandler();  //Correct context when called directly
   //Note: I haven't actually tested this persay but this function is no different
   //than any other functionso a direct call should certainly not be problem.

This is a jquery interface from jquery.d.ts:

export interface IDialogEvent extends DialogEvent {
    (event: Event, ui: DialogUIParams): void;
}

This is my custom interface mimicking partial functionality of the DialogOptions interface of jquery.d.ts:

export interface IDialogOptions {
    open: IDialogEvent;
}

export class DialogClass implements IDialogOptions { 

    //Dialog options
    public open: IDialogEvent;

    //Class related fields
    public someField: any;
    public dialogEl: JQuery;

    constructor() { 
        this.open = this.OpenHandler;
        this.dialogEl = $("<div></div>").dialog(this); 
        //Passing "this" initializes the dialog by mapping relevant class fields
        //to the dialog's "option" object, in this case the only "relevant" field is "open".
    }

    public OpenHandler(event: Event, ui: DialogUIParams) { 
        var value = this.someField; //BAD. "this" is not type BaseClass
    }

    public NonEventHandlerMethod() { 
        var value = this.someField; //GOOD. "this" is type BaseClass
    }  
}

var dialog = new DialogClass();
dialog.dialogEl.dialog("open"); 

The last line fires OpenHandler() but inside it, this is not type BaseDialog (unlike in NonEventHandlerMethod).

The reason I need an event handler function for the dialog options field and the reason why I can't simply do this:

 export class DialogClass implements IDialogOptions { 
     ...
      constructor() { 
          this.open = () => {
                //event handling logic
          };
          ...
      }
      ...
 }        

is because I need to add additional open-event handling logic in classes that extend DialogClass and there is no differentiation between this.member and super.member... there is only differentiation between this.function() and super.function():

 export class LoginDialog extends DialogClass { 
     ...
      constructor() { 
          this.open = this.OpenHandler;
          ...
      }

      public OpenHandler(event: Event, ui: DialogUIParams) { 
           super.OpenHandler(); //Base handling logic

           //Additional handling logic
      } 
      ...
 } 

I think this may be a bug because

   export class DialogClass implements IDialogOptions { 
     ...
      constructor() { 
          this.open = () => {
                var test = this.someField;  //Correct context
          };
          ...
      }
      ...
   }  

and calling the method directly:

   var dialog = new DialogClass();
   dialog.OpenHandler();  //Correct context when called directly
   //Note: I haven't actually tested this persay but this function is no different
   //than any other functionso a direct call should certainly not be problem.
Share Improve this question edited Feb 12, 2013 at 22:23 parliament asked Jan 23, 2013 at 18:38 parliamentparliament 22.9k39 gold badges154 silver badges246 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 14

TypeScript follows the usual JavaScript scoping conventions, so this will be dependent on context. If you have a method on a class that fires based on an event, this will be the event target. When you directly call a method on a class, this will be the class.

If you want to get around this, you can take advantage of how JavaScript walks up the scope chain by giving this an alias...

Here is one way to do that:

this.open = () => { this.OpenHandler(this); };

The arrow-function syntax creates and alias name _this in the JavaScript.

public OpenHandler(context: DialogClass, event: Event, ui: DialogUIParams) { 
    var value = context.someField;
}

We accept the cleverly aliased version of this as a parameter and context.someField should have the value we are after.

发布评论

评论列表(0)

  1. 暂无评论