0

When I pass an anonymous function with fat arrows as a socket.io callback and then call another method in the same object (as follows) the scope of @ is correct:

module.exports = class InviteCreateSocket extends AbstractSocket
  register: () ->
    @socket.on 'invite:create', (data, callback) => @create data, callback

  create: (data = {}, callback = @_noop) ->
    # This returns an instantiated InviteCreateSocket. Bonzer!
    console.log @

However, if I pass it in directly, the scope is now of the socket, as if I had run the previous code with thin arrows:

module.exports = class InviteCreateSocket extends AbstractSocket
  register: () ->
    @socket.on 'invite:create', @create

  create: (data = {}, callback = @_noop) ->
    # This returns the socket. Not bonzer. Not bonzer at all.
    console.log @

So, is there a nice clean way of getting object scope without having to relay them through a fat anonymous function? The first method works but seems a bit clumsy and obviously requires having to synchronise the parameters in all the methods. Thanks in advance!

Matt Fletcher
  • 8,182
  • 8
  • 41
  • 60

2 Answers2

3

Why not use the fat arrow for the functions belonging to the class, thus binding them correctly to the context of the class (and it's instances) - this is more how it is intended to work.

module.exports = class InviteCreateSocket extends AbstractSocket
  register: () =>
    @socket.on 'invite:create', @create
    return

  create: (data = {}, callback = @_noop) =>
    console.log @
    return

Also, don't forget to add empty returns in function which are not intended to return something.

Exinferis
  • 689
  • 7
  • 17
  • Ah, fat arrows on class methods actually internally uses bind. That sounds pretty good and should have been obvious really. Thanks! (ps, regarding the empty returns, there's more code later on in the functions, I just stripped it down for SO) – Matt Fletcher May 15 '15 at 09:39
  • See also this answer of mine about fat arrows in CoffeeScript and why I avoid thin arrows: http://stackoverflow.com/a/17431824/517371 – Tobia Nov 03 '15 at 18:11
2

Not a Coffeescript expert, but I'd guess no. It's because Coffeescript is compiled to JavaScript, and JavaScript equivalent is going against you. The issue is this: you can't have a reference to a method, because to be a method it has to be invoked on a recipient.

var bar = foo.create;
bar();

is very different than

foo.create();

because the former does not set this to foo. So when you just pass @create, it dissociates your method from your object, and @ is not correct any more within your method-that-is-now-just-a-function.

Now, back to CoffeeScript: the uglier way to solve your parameter dilemma is => @create(arguments...). This should pass all arguments to @create, whatever they are. However, the nicer way to do it is to simulate what the fat arrow does using a plain JS technique: @create.bind(@).

There may be something nicer by someone more knowledgeable in CoffeeScript, though.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Thanks for taking the time to reply. Bind does indeed work. I would too be curious about whether there's a coffee solution, so I'll accept your answer if and when no alternative comes through! – Matt Fletcher May 15 '15 at 09:24