Coffeescript 'this' inside jQuery .each()

Coffeescript 'this' inside jQuery .each()

本文关键字:each this Coffeescript inside jQuery      更新时间:2023-09-26

我有一些像这样的咖啡脚本:

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()内的类实例-它目前没有这样做。

.each函数之外使用_this = this之类的东西并传递它也不是一个很好的解决方案,因为我在processRow中引用了许多类变量。

任何想法吗?我错过了什么明显的东西吗?谢谢!

jQuery.each传递当前元素作为回调的第二个参数,所以你没有为jQuery保留this:

processRows: ->
    $("#my-table>tr").each (index, element) =>
        id = $(element).attr("id")
        @processRow id
注意使用粗箭头 (=>)语法回调函数;它将函数的上下文绑定到this的当前值。(回调函数中的this始终与您定义该函数时的this相同)

你说

.each函数之外使用_this = this之类的东西并传递它也不是一个很好的解决方案,因为我在processRow中引用了许多类变量。

这是最有效的解决方案。JavaScript的this是一个奇怪的野兽;您可以使用=>运算符将其固定在嵌套函数中,正如arnaud576875在他的回答中所建议的那样(这是优雅的,但效率低下),或者您可以将this复制到另一个变量(这是有效的,但不优雅)。选择权在你。

请注意,一些现代浏览器支持每个函数的bind方法,这比CoffeeScript的=>更有效。有一个开放的票证让=>在可用时使用本机bind: https://github.com/jashkenas/coffee-script/pull/1408

附录:当然,比上述任何一种更有效的替代方法是写

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

也可以解决你的this问题

你的代码…

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

Transpiles:

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函数的静态属性