Подтвердить что ты не робот

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

У меня есть некоторый 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.

Любые мысли? Мне что-то не хватает? Спасибо!

4b9b3361

Ответ 1

jQuery.each передает текущий элемент как второй параметр обратного вызова, поэтому вам не нужно резервировать this для jQuery:

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

Обратите внимание на использование синтаксиса жирной стрелки (=>) для функции обратного вызова; он связывает контекст функции с текущим значением this. (this в функции обратного вызова всегда один и тот же this как тот, который был выбран в момент, когда вы определили функцию.)

Ответ 2

Вы говорите

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

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

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

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

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

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

Ответ 3

Ваш код...

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