从事件处理程序回调调用的函数中“this”的值?

Posted

技术标签:

【中文标题】从事件处理程序回调调用的函数中“this”的值?【英文标题】:Value of `this` in a function called from an event handler callback? 【发布时间】:2013-06-07 13:59:59 【问题描述】:

我已经注释了相关代码。我通过反复试验发现,我必须在事件处理程序和命名回调中都使用绑定才能使事情正常工作。

我没有发现这很直观,因为我认为命名回调会调用函数,其值 this 指向包含的对象字面量。

我了解事件处理程序需要绑定 b.c。通常回调会指向触发事件的元素。

但是第二个绑定,(我验证是必需的),我不明白机制/概念。

// * 表示焦点区域。

NS.parsel(
    Name: 'MSimMenu',
    E: 
        hold_name:         '#hold_name',
        wrap_bottom:       '#wrap_bottom'
    ,
    A: 
        time_out_id:        null,
        TIME_DELAY:         1000
    ,
    init: function () 
        var self = this;
        self.E.hold_name.addEventListener(   "mouseover",   self.mouseOverTop.bind(self),    false);
        self.E.wrap_bottom.addEventListener( "mouseover",   self.mouseOverBottom.bind(self), false);
        self.E.wrap_bottom.addEventListener( "mouseout",    self.mouseOut.bind(self),        false);
        self.E.hold_name.addEventListener(   "mouseout",    self.mouseOut.bind(self),        false);
    ,

    // callbacks

    mouseOverTop: function () 
        NS.clearTimeout(this.A.time_out_id);
        this.showBottom();
    ,
    mouseOverBottom: function () 
        NS.clearTimeout(this.A.time_out_id);
    ,        
    mouseOut: function () 

        // * this regards the question
        // bind is required here for hideBottom to have correct value of this

        this.A.time_out_id = NS.setTimeout(this.hideBottom.bind(this), this.A.TIME_DELAY);
    ,

    // called from callbacks

    showBottom: function () 
        this.E.wrap_bottom.style.visibility = 'visible';
    ,
    hideBottom: function () 
        this.E.wrap_bottom.style.visibility = 'hidden';
    
);

【问题讨论】:

【参考方案1】:

这是因为this 是根据函数的调用方式确定的。在 setTimeout 回调的情况下,它不是在您的 NS 对象的上下文中调用,而是作为一个独立的函数调用。在这种情况下,this 未定义,回退到全局对象。

关于绑定的事件处理程序,您可能对另一种方法感兴趣,它使您的对象实现EventHandler 接口。 ***er 的一位同事最近一直在建议,请参阅How to Implement DOM Data Binding in javascript 的已接受答案。

【讨论】:

@pure_code.mom 我不确定他所说的“直接调用者”是什么意思。但是如果你调用NS.hideBottom,那么this就是NS;但是如果你做var func = NS.hideBottom; func(),那么它将是全局对象。或者,如果您使用var o = fn: NS.hideBottom ; o.fn(),那么this 将是o @pure_code.mom 哈哈哈,谢谢!还有一件事可以为您澄清这个问题:“奇怪”的效果是因为函数/方法不属于任何特定对象,它们只是作为引用附加;事实上,同一个函数对象可以有多个“父”对象,如我上面评论中的示例所示。所以JS无法知道函数绑定到哪个对象,必须手动绑定。【参考方案2】:

在 JavaScript 中,当一个函数调用另一个函数时,'this' 关键字会改变上下文。上下文是函数的直接调用者。

【讨论】:

以上是关于从事件处理程序回调调用的函数中“this”的值?的主要内容,如果未能解决你的问题,请参考以下文章

EventEmitter事件处理器中的this问题

React--事件处理

Node.js 事件循环

Node.js 事件循环

立即从同步代码执行异步回调

异步回调,事件,线程池与协程