0

Coffeescript: 'this' внутри jQuery .each()

11

У меня есть код на CoffeeScript, который выглядит следующим образом:

class foo:
    @bar = 'bob loblaw'

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

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

Моя проблема в том, что я хочу, чтобы this ссылался на контекст .each внутри цикла, чтобы получить значение id, но при этом this также должен ссылаться на экземпляр класса внутри foo.processRow(), что в текущем варианте не выполняется.

Использовать что-то вроде _this = this за пределами функции .each и передавать его далее – не лучшее решение, так как мне нужно обращаться к многим переменным класса внутри processRow.

Есть ли у кого-то идеи? Может, я упустил что-то очевидное? Спасибо!

2 ответ(ов)

0

Вы говорите:

Использовать что-то вроде _this = this вне функции .each и передавать его вокруг — не лучшее решение, поскольку я ссылаюсь на множество переменных класса внутри processRow.

На самом деле, это наиболее эффективное решение. this в JavaScript — странная штука; вы можете зафиксировать его внутри вложенной функции, используя оператор =>, как предлагает arnaud576875 в своем ответе (это элегантно, но неэффективно), или скопировать this в другую переменную (что эффективно, но не элегантно). Какой путь выбрать — решать вам.

Обратите внимание, что некоторые современные браузеры поддерживают метод bind для каждой функции, который более эффективен, чем => в CoffeeScript. Существует открытый тикет для того, чтобы => использовал нативный bind, когда он доступен: https://github.com/jashkenas/coffee-script/pull/1408

Дополнение: Конечно, более эффективной альтернативой любому из вышеперечисленных решений будет запись:

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

что также решит вашу проблему с this.

0

Ваш код...

class foo
    @bar = 'bob loblaw'

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

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

Компилируется в...

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;
})();

Выводит предположение о текущем контексте, в который это транслируется. К сожалению, поскольку jQuery управляет контекстом, вам нужно будет явно указывать его или объявить ссылку на this вашего класса.

Кстати, есть и другие проблемы с сгенерированным кодом, обратите внимание на этот сокращенный случай:

class foo
    @bar = 'bob loblaw'

    getBar: () ->
        @bar

Транспилируется в:

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

Результаты попытки использовать этот код:

> foo.bar;
"bob loblaw"

> var f = new foo();
undefined

> f.getBar();
undefined

Ваш код, похоже, ожидает, что @bar является собственным свойством, но он создается как статическое свойство функции foo.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь