【问题标题】:call functions within event handler在事件处理程序中调用函数
【发布时间】:2013-09-20 20:29:47
【问题描述】:

我在Javascript代码中写了2个函数如下

Manager = FormManager.extend({
    First: function () {
     var response = this.Second("Feature"); //I'm able to get the alert

     //I have added a click event handler
     $('#element').on('click', function(){
       var newResponse = this.Second("Bug"); //The alert is not poping
     });

    }

    Second: function (type) {
     alert(type);
     //Performs certain operation
    }
});

错误: Uncaught TypeError: Object # has no method 'Second'

我也试过不使用 this 关键字,如

Second("Bug") // Error: There is no method

而在我正在玩的程序中,这是一种简化的格式(为了显示一个简单的示例)。我正在努力找出原因。

谁能指引我正确的道路?

【问题讨论】:

    标签: javascript javascript-events event-handling jquery


    【解决方案1】:

    您使用的this 不正确。试试这个方法。处理程序中的this 代表#element 而不是函数本身的上下文。

     var self = this; //cache the context here
     $('#element').on('click', function(){
       var newResponse = self.Second("Bug"); //Access it with self
     });
    

    我还认为您在First 函数定义之后和Second 函数之前缺少一个逗号。

    Fiddle

    您提供的回调的原因是从元素的上下文中调用,因此您的 this 上下文会发生变化。 this context 是指调用回调的上下文。但是还有其他方法可以解决这个问题,例如在将回调与 jquery 绑定时使用 $.proxy,使用 EcmaScript5 Function.prototype.bind 等。但理想情况下,您不想这样做,因为大多数情况下您需要处理程序内部的元素。

    【讨论】:

    • +1 非常感谢您的精彩解释。我明白了你的意思,对我来说,这是我使用这种类型的函数声明的新东西。这种方法声明有什么特别之处吗?
    • @user1671639 这没什么不好。但是,如果您正在寻找更多的对象模型类型声明,您可以查看 EcmaScript5 Object.create 模式。但是,当您在 Node.js 等租户上运行时,这同样会有所帮助,但只有较新的浏览器支持这一点。否则,这些更多的是 statix 方法绑定,因为您不需要它们上的实例。
    • 再次感谢您。我明白了,因为我们使用的是backbonejs,这也是他们采用这种方法的原因。很抱歉问这个问题,是否有任何快速链接可以参考我关于 JS/jQuery 中的不同函数声明(如果有)。
    • 每个框架都使用许多模式。您可以查找 javascript 模式或更新的 ecma5 ,这里是 jquery plugin authoring pattern
    【解决方案2】:

    每次在函数中使用this 上下文变量时,都必须考虑它的值。

    具体而言,该值将是调用者指定的任何值,无论是使用myObj.mymethod(...)、mymethod.call(myObj, ...)还是mymethod.apply(myObj, [ ... ])。

    当您的匿名函数 $('#element').on('click', ...) 被调用时,jQuery 会将上下文设置为 HTML DOM 元素 - 它不再引用您的对象。

    最简单的解决方法是在回调之外获取this 的副本,然后在闭包内引用该副本,即:

    var that = this;
    $('#element').on('click', function() {
         // use that instead of this, here
         console.log(this);    // #element
         console.log(that);    // your object
    });
    

    另一种方法是使用Function.prototype.bind:

    $('#element').on('click', (function() {
         console.log(this);    // your object
    }).bind(this));
    

    或者使用 jQuery,你可以使用 $.proxy 来达到同样的效果,因为 .bind 是一个 ES5 函数。

    我实际上更喜欢var that = this 方法,因为它不会破坏this 引用与事件关联的元素的jQuery 约定。

    【讨论】:

    • +1 感谢您的宝贵回答,我通常会声明像function First() { 或First = function() { 这样的函数。这种方法声明有什么特别之处吗?
    • 抱歉,我从@PSL 得到了答复。感谢您指点我$.proxy,这对我来说很新
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    相关资源
    最近更新 更多