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
.
Любые мысли? Мне что-то не хватает? Спасибо!
Ответы
Ответ 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