关于javascript:尝试通过传入函数来绑定回调会抛出错误

Trying to bind a callback by passing in the function throws an error

我只想在输入使用 jQuery 1.7.2 和 Backbone.js 更改值时触发一个事件。

目前我有以下(有效)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
MyView: Backbone.View.extend({
  initialize: function() {

    this.colorInput = $("<input />", {
        "id":"color",
        "name":"color",
        "value": this.model.get("color")
    });

    var self = this;
    this.colorInput.on("change", function() {
      self.changeColor();
    });

  },
  changeColor: function() {
    var color = this.colorInput.val();
    this.model.set("color", color);
  }
});

我试图用另一种方式来做,我只是传入我的函数。

1
this.colorInput.on("change", this.changeColor, this);

但是当试图这样做时,它会抛出错误

((jQuery.event.special[handleObj.origType] || {}).handle ||
handleObj.handler).apply is not a function
.apply( matched.elem, args );

(第 3332 行)

我无法弄清楚。任何想法为什么这种方式不起作用?


你混淆了 jQuery 的 on:

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

与 Backbone 的 on:

object.on(event, callback, [context])

Backbone 将上下文作为第三个参数,而 jQuery 没有。看起来 jQuery 的 on 正在将您的第三个参数解释为 handler(eventObject) 并尝试像函数一样调用它,这将解释您看到的错误消息。

通常你会这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
MyView: Backbone.View.extend({
  events: {
    'change input': 'changeColor'
  },
  initialize: function() {
    this.colorInput = $("<input />", {
      "id":"color",
      "name":"color",
      "value": this.model.get("color")
    });
  },
  render: function() {
    this.$el.append(this.colorInput);
    return this;
  },
  changeColor: function() {
    var color = this.colorInput.val();
    this.model.set("color", color);
  }
});

让 Backbone 的事件委托系统来处理。

  • 1,是的,这里的意见相同。我也有一个工作示例的问题,onlive 创建的 DOM 元素没有触发 change 事件,我放弃了,因为这不是与问题相关的问题。
  • @fguillen:我取消了一半的编辑,我认为 .on 正在对其第一个参数进行 isPlainObject 检查以选择它使用的形式,第一个参数不是事件映射,所以它与第一个参数一起使用.on 的形式,我们回来尝试像函数一样调用视图对象。你是否有"直到焦点改变才会触发改变"的问题?
  • @muistooshort,这是完美的。感谢您的解释和代码示例。这种方式要好得多,而且效果很好。我必须将事件选择更改为 change #color 才能使其正常工作,但除此之外它很棒。再次感谢。
  • @fguillen:我把事件规范倒过来了,'input change' 应该是(现在是)'change input':jsfiddle.net/ambiguous/xD7Xm
  • @Brandon:我的事件规范倒退了(呃!),请参阅我对 fguillen 的最后评论。
  • @muistooshort 你看,我知道我错过了一些东西,只是参数的数量......很容易:P
  • @muistooshort 关于您是否遇到"直到焦点更改才触发更改"问题?我不知道这个问题,但很有可能。在我的实验中,我通过代码修改 colorInput.val() 并且没有触发事件,如下所示:jsfiddle.net/fguillen/qZ8aN
  • @fguillen:在值发生变化并且焦点发生变化(或多或少)之前不会触发事件:stackoverflow.com/a/7055771/479863
  • @muistooshort 这个 HTML 规范是在实现 JS 之前完成的 :)... 我明白了,如果我们看书,行为是正确的,但我仍然打开了一个 jQuery 错误只是为了对此产生噪音。
  • 尽管您的评论没有直接适用,但您确实帮助了我,让我知道正在发生的事情,所以 1 给您。我试图在窗口滚动处理程序中调用 lodash 的 debounce(),但我有一个错字并将 debounce() 的参数传递给 on() 的参数。


这是为遇到此问题的 Google 员工准备的。我遇到了完全相同的问题,发生的事情是报告错误的位置和实际发生错误的位置在两个不同的地方。

一行代码已经过时,看起来像

1
2
3
$('#modal').on('click', function(e) {
   // Execute invalid code here.
});

另一行代码类似:

1
2
3
$('#modal').on('click', function(e) {
   // Execute valid code here.
});

错误是第一次调用不是一个真正的函数,所以错误是准确的,第二个被调用的处理程序不是一个真正的函数,jQuery无法完成它,但它总是表现得好像它发生在第二个函数调用。

我会说,如果您遇到此错误,请删除任何可能触发的额外事件处理程序,看看是否可以解决问题。