Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using arrow functions in TypeScript: how to make them class methods?

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!

like image 278
Robert Avatar asked Dec 12 '12 23:12

Robert


People also ask

Can arrow functions be used as methods?

Arrow functions don't have their own bindings to this , arguments , or super , and should not be used as methods. Arrow functions cannot be used as constructors.

Can I use arrow functions in TypeScript?

ES6 version of TypeScript provides an arrow function which is the shorthand syntax for defining the anonymous function, i.e., for function expressions. It omits the function keyword. We can call it fat arrow (because -> is a thin arrow and => is a "fat" arrow). It is also called a Lambda function.

Can you use arrow functions to create object methods in JavaScript?

Arrow functions cannot be used to write object methods because, as you have found, since arrow functions close over the this of the lexically enclosing context, the this within the arrow is the one that was current where you defined the object.

Can we use arrow function in class?

You should avoid using arrow functions in class as they won't be the part of prototype and thus not shared by every instance. It is same as giving the same copy of function to every instance.


2 Answers

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));

like image 140
Ryan Cavanaugh Avatar answered Sep 24 '22 06:09

Ryan Cavanaugh


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.

like image 32
BreeeZe Avatar answered Sep 24 '22 06:09

BreeeZe