Reputation: 71
I'm fairly experienced programming but quite new to TypeScript.
Trying to use it with jQuery and immediately ran into the 'this' issue with callbacks (such as $(document).ready.
Using $.proxy() is one way to go, but using TypeScript's arrow (lambda) functions seemed much better. But I only see them used as expressions — that is the entire function is defined inline. I would like to be able to set up arrow functions that could be called as methods of my class, something like (in pseudocode):
class Something {
constructor() {
$(' nav li').click(this.menuClick);
}
private menuClick (and this would be an arrow function to preserve 'this')()=>
// it would call this.anotherMethod()
// plus lots of other things so it won't easily fit inline
private anotherMethod():void {
// do something on the menu click, several lines perhaps,
}
}
I come from an OOP background in AS3, and that's how I was able to do it -- 'this' was readily accessible or it was clear how to access it. I'm keen to use TypeScript to get past the OOP hurdle I'm having with Javascript plain -- but it seems cumbersome (to me) to have to proxy all the jQuery calls (I know there are classes out there to do this for me, but is there a simpler way, with arrow/lambda functions?).
Have patience if I'm not grokking the obvious, but it ain't obvious to me!
Upvotes: 7
Views: 6934
Reputation: 86
The short answer:
If you change : $(' nav li').click(this.menuClick);
into : $(' nav li').click(() => this.menuClick());
then this
will be your class 'Something' inside the menuClick
method.
Upvotes: 2
Reputation: 220884
The reason there isn't a way to do this by default is that it's a tremendous runtime cost in terms of per-instance memory consumption if done automatically. Rather than having one base prototype object with all the functions in it and each class instance pointing to that prototype for its function definitions, you end up having a closure per function for every instance of the class.
There might be better type system support for this in the future, but for now, dealing with this
binding issues is just a tax you have to pay when writing JavaScript of any flavor. Hopefully as things like TypeScript gain momentum, library authors will reduce their usage of this
-stomping (though the DOM will never have that luxury).
The upside is that in TypeScript, it's not a huge amount more code when you do need to re-re-bind this
:
$(' nav li').click(() => this.menuClick());
or
$(' nav li').click(this.menuClick.bind(this));
Upvotes: 11