Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coffeescript 'this' inside jQuery .each()

People also ask

How do I declare a variable in CoffeeScript?

In JavaScript, before using a variable, we need to declare and initialize it (assign value). Unlike JavaScript, while creating a variable in CoffeeScript, there is no need to declare it using the var keyword. We simply create a variable just by assigning a value to a literal as shown below.

Is CoffeeScript typed?

But it is a strictly typed programming language. CoffeeScript has high object-oriented capabilities. But it is a dynamic type of programming language.

How do I use CoffeeScript in HTML?

If you are looking to implement coffee script in html, take a look at this. You simple need to add a <script type="text/coffeescript" src="app. coffee"></script> to execute coffee script code in an HTML file.


jQuery.each passes the current element as second parameter of the callback, so you don't have to reserve this for jQuery:

processRows: ->
    $("#my-table>tr").each (index, element) =>
        id = $(element).attr("id")
        @processRow id

Notice the use of the fat arrow (=>) syntax for the callback function; it binds the function's context to the current value of this. (this in the callback function is always the same this as the one at the time you defined the function.)


You say

Using something like _this = this outside the .each function and passing it around isn't a great solution, either, since I reference many class variables inside processRow.

This is the most efficient solution, though. JavaScript's this is a strange beast; you can keep it fixed inside of a nested function using the => operator, as arnaud576875 sugests in his answer (which is elegant but inefficient), or you can copy this to another variable (which is efficient but inelegant). The choice is yours.

Note that some modern browsers support a bind method on every function, which is more efficient than CoffeeScript's =>. There's an open ticket to have => use the native bind when available: https://github.com/jashkenas/coffee-script/pull/1408

Addendum: Of course, a more efficient alternative than any of the above would be to write

for element, index in $('#my-table>tr')
  ...

which would also solve your this problem.


Your code...

class foo
    @bar = 'bob loblaw'

    processRows: ->
        $("#my-table>tr").each ->
            id = $(this).attr("id")
            @processRow id

    processRow: (id) ->
        console.log @bar + id

Is transpiled to...

var foo;
foo = (function() {
  function foo() {}
  foo.bar = 'bob loblaw';
  foo.prototype.processRows = function() {
    return $("#my-table>tr").each(function() {
      var id;
      id = $(this).attr("id");
      return this.processRow(id);
    });
  };
  foo.prototype.processRow = function(id) {
    return console.log(this.bar + id);
  };
  return foo;
})();

Which has assumed much about about the current context that it is translating to. Unfortunately, since jQuery manages context, you'll have to be explicit or declare a reference to your class's this.

Incidentally, there are other issues with that generated code, take a look at this reduced case:

class foo
    @bar = 'bob loblaw'

    getBar: () ->
        @bar

Transpiles to:

var foo;
foo = (function() {
  function foo() {}
  foo.bar = 'bob loblaw';
  foo.prototype.getBar = function() {
    return this.bar;
  };
  return foo;
})();

The results of attempting to use this piece of code:

> foo.bar;
"bob loblaw"

> var f = new foo();
undefined

> f.getBar();
undefined

Your code seems to expect that @bar is an own property, but it's being created as a static property of the foo function