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


December 2018


2k time


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: ->

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.

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'.

3 answers


Вы должны использовать либо вызов или применять методы , поскольку они устанавливают сферу функции (значение этого). Погрешность результатов , поскольку сфера по умолчанию является windowобъектом.


Как matyr отмечает в своих комментариях, линия

oauth.authorize( this )

не вызывает this.afterLoginназываться как обратный вызов с помощью oauth.authorize; вместо этого, это эквивалентно

oauth.authorize this.afterLogin()

Предполагая , что вы хотите , this.afterLoginчтобы использовать в качестве обратного вызова с помощью oauth.authorize, ответ megakorre дает правильный CoffeeScript идиомы. Альтернативный подход поддерживается многими современными средами JS, так как matyr указывает, должен был бы написать

oauth.authorize( this.afterLogin.bind this )

Там нет CoffeeScript стенографии для этого, отчасти потому , что Function::bindне поддерживается всеми основными браузерами. Вы можете также использовать bindфункцию из библиотеки , как Underscore.js :

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

Наконец, если вы должны были определить someobjectкак класс вместо этого, вы могли бы использовать , =>чтобы определить afterLoginтаким образом, чтобы он всегда привязывается к примеру, например ,

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

someobject = new SomeClass

Вы можете поставить лямбда в вызове функции, как так

auth.authorize(=> @afterLogin())