javascript - "this"未使用原型(prototype)引用 this-reference

标签 javascript dom-events prototype

<分区>

今天我在使用 Javascript 的 prototypethis 引用时遇到了一个非常奇怪的问题。

基本上,我有两个对象。一个对象使用 div 元素,并且可以在 div 上注册一个 onclick 事件。另一个对象利用此功能并使用第一个对象注册 onclick 事件。

代码如下:

我的第一个对象,负责处理 div:

DivObject = function() {};
DivObject.prototype.setClickListener = function(clickListener){
    document.getElementById("myDiv").onclick = function(e){
        clickListener(e);
    };
};

我的第二个对象使用此功能:

MainObject = function(){
    this.myString = "Teststring";
    this.divObj = new DivObject();
    this.divObj.setClickListener(this.handleClick);
};

MainObject.prototype.handleClick = function(e){
    // do something with e
};

问题是,在 MainObject.prototype.handleClick 中,this 引用引用了 window 对象,而不是 主要对象。因此,此函数内的 console.log(this) 记录 [Object window]

You can see this behaviour on jsfiddle.

作为解决方法,我使用 setClickListener 函数,如下所示:

var thisRef = this;
this.divObj.setClickListener(function(e){
    thisRef.handleClick(e);
});

现在,我的 handleClick 函数中的 this 引用引用了我的 MainObject(如我所愿)。

See this workaround on jsfiddle.

我的问题是:

为什么 this 引用一次引用 window 对象而另一次引用我的对象的 this 引用?它在某处被覆盖了吗?我一直认为在我的对象中使用 this 我可以确定它真的是我对象的 this 引用吗?我现在使用的解决方法是应该如何解决这个问题,还是有任何其他更好的方法来处理这种情况?

最佳答案

您的问题:

Why does the this reference one time refer to the window object and one time to the this reference of my object?

除了使用 bind 之外,函数的 this 的值由调用函数的方式设置。当你这样做时:

this.divObj.setClickListener(this.handleClick);

您正在分配一个函数引用,因此该函数稍后会在没有任何限定的情况下被调用(即它被称为 handleClick 而不是 this.handleClick)。在进入函数时,因为它的 this 没有被调用设置,它将默认为全局(窗口)对象,或者在严格模式下保持未定义。

Is it overridden somewhere?

不,this 的值是在进入执行上下文时设置的。你不能覆盖它或直接分配给它,你只能在调用中设置它(例如作为一个对象的方法,使用newapplycall) 或使用 bind(另外,箭头函数采用其封闭词法执行上下文的 this)。

I always thought using this in my object I can be sure that it is really the this reference of my object?

在您进行分配时,this 就是您所期望的。但是您正在为一个函数分配一个引用,而不是调用该函数,因此它的 this 不是在那个时候设置的,而是在稍后被调用时设置的。

Is the workaround I am using now the way how this problem should be solved or are there any other, better way to handle this case?

您的解决方法很好(也是一个常见的修复方法),它会创建一个闭包,因此可能会产生轻微的内存后果,但并不严重。对于非常旧的 IE 版本,它会由于涉及 DOM 对象的循环引用而造成内存泄漏,但这是固定的。

bind 解决方案从清晰度和维护 Angular 来看可能更好。请记住为没有内置 bind 支持的浏览器添加“猴子补丁”。

请在 SO 上发布代码,不能保证在其他地方发布的代码将继续可访问。解决代码:

MainObject = function(){
    this.myString = "Teststring";
    this.divObj = new DivObject();
    var thisRef = this;
    this.divObj.setClickListener(function(e){
        thisRef.handleClick(e);
    });
};

关于javascript - "this"未使用原型(prototype)引用 this-reference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12702698/

相关文章:

javascript - 选择内容以 '+' 开头的所有 <a> 元素

javascript - 尝试从在线 api.fixer.io 获取 json

javascript - 收到 JQUERY "syntax error, unrecognized expression"

javascript - 由于目标被视为被动,无法阻止被动 Konva 事件监听器中的默认设置

javascript - 为什么我应该使用事件委托(delegate)而不是 queryselectorAll

javascript - 如何将子对象的范围限制到父对象?

javascript - HTML5 LocalStorage 的全日历

javascript - 在 IE9 beta 中阻止点击事件传播的最佳方法是什么?

无法访问 JavaScript __proto__

javascript - Backbone Marionette : put methods on instance/constructor or prototype when extending objects