How can I use Coffeescript 'this' from wit

2020-02-25 23:09发布

问题:

When using classes in Coffeescript, I've stumbled upon a major problem, let me illustrate

class Bet
  constructor: () ->

  placeBet: ->
    $('#chips > div').bind 'click', ->
      amount = $(this).attr 'id'
      pile = $(this)
      switch amount
        when "ten" then this.bet pile, amount #This line causes a problem

  bet: (pile, amount) ->
    alert 'betting!'

The call to this.bet above generates the following error:

Uncaught TypeError: Object # has no method 'bet'

So, currently the instance method of my class is not being called, How can I correctly call the bet method of my class without it colliding with the jQuery selector's this (Which is what I suppose is happening now)?

Thank you very much in advance!

回答1:

Try this:

class Bet
  constructor: () ->

  placeBet: ->
    that = this
    $('#chips > div').bind 'click', ->
      amount = $(this).attr 'id'
      pile = $(this)
      switch amount
        when "ten" then that.bet pile, amount #This line causes a problem

  bet: (pile, amount) ->
    alert 'betting!'


回答2:

Another solution is to use the CoffeeScript fat-arrow in the click event handler then your scope would be the same as if you were inside the placeBet function. You would then use e.currentTarget to get a reference to the target object instead of using $(this)

class Bet
  constructor: ->

  placeBet: ->
    $('#chips > div').bind 'click', (e) =>
      target = $(e.currentTarget)
      amount = target.attr 'id'

      switch amount
        when "ten" then @bet target, amount #This line causes a problem

  bet: (pile, amount) ->
    alert 'betting!'


回答3:

You script turns into this:

var Bet;

Bet = (function() {

  function Bet() {}

  Bet.prototype.placeBet = function() {
    return $('#chips > div').bind('click', function() {
      var amount, pile;
      amount = $(this).attr('id');
      pile = $(this);
      switch (amount) {
        case "ten":
          return this.bet(pile, amount); //<< you cannot do this!!!
      }
    });
  };

  Bet.prototype.bet = function(pile, amount) {
    return alert('betting!');
  };

  return Bet;

})();

What you need is a reference to _self which is is the Bet object:

class Bet
  constructor: () ->

  placeBet: ->
    _self = this
    $('#chips > div').bind 'click', ->
      amount = $(this).attr 'id'
      pile = $(this)
      switch amount
        when "ten" then _self.bet pile, amount #This line causes a problem

  bet: (pile, amount) ->
    alert 'betting!'