开发者

Is there a way to avoid using 'call' in Coffeescript?

I'm writing a simple Twitter client to play with coffeescript. I have an object literal with some functions that call each other via callbacks.

somebject =
  foo: 'bar'
  authenticateAndGetTweets: ->
    console.log "Authorizing using oauth"
    oauth = ChromeExOAuth.initBackgroundPage(this.oauthdetails)
    oauth.authorize( this.afterLogin.call this )
  afterLogin: ->
    this.getTweets(this.pollinterval)

This code works perfectly. Edit: actually this.afterlogin should be sent as a callback above, not ran immediately, as Trevor noted below.

If, within authenticateAndGetTweets, I removed the 'call' and just ran:

oauth.authorize( this.afterLogin )

and don't use 'call', I get the following error:

Uncaught TypeError: Object [object DOMWindow] has no method 'getTweets

Which makes sense, since 'this' in afterLogin is bound to the thing that initiated the callback rather than 'someobject' my object literal.

I was wondering if there's some magic in Coffeescript I could be doing instead of 'call'. Initially I thought using the '=>' but the code will give the same error as above if '=>' is used开发者_Go百科.

So is there a way I can avoid using call? Or does coffeescript not obviate the need for it? What made '=>' not work how I expected it to?

Thanks. I'm really enjoying coffeescript so far and want to make sure I'm doing things 'the right way'.


As matyr points out in his comments, the line

oauth.authorize( this.afterLogin.call this )

doesn't cause this.afterLogin to be called as a callback by oauth.authorize; instead, it's equivalent to

oauth.authorize this.afterLogin()

Assuming that you want this.afterLogin to used as a callback by oauth.authorize, megakorre's answer gives a correct CoffeeScript idiom. An alternative approach supported by many modern JS environments, as matyr points out, would be to write

oauth.authorize( this.afterLogin.bind this )

There's no CoffeeScript shorthand for this, partly because Function::bind isn't supported by all major browsers. You could also use the bind function from a library like Underscore.js:

oauth.authorize( _.bind this.afterLogin, this )

Finally, if you were to define someobject as a class instead, you could use => to define afterLogin such that it's always bound to the instance, e.g.

class SomeClass
  foo: 'bar'
  authenticateAndGetTweets: ->
    console.log "Authorizing using oauth"
    oauth = ChromeExOAuth.initBackgroundPage(this.oauthdetails)
    oauth.authorize(this.afterLogin)
  afterLogin: =>
    this.getTweets(this.pollinterval)

someobject = new SomeClass


you can put a lambda in the function call like so

auth.authorize(=> @afterLogin())


You have to use either the call or apply methods because they set the scope of the function (the value of this). The error results because the default scope is the window object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜