25

下面我在 Javascript 中创建一个对象。在构造函数中,我正在设置一个事件侦听器。问题是当事件被触发时,无法找到 this.prop 并且 undefined 打印出来。我该如何解决这个问题?

   var someObj = function someObj(){
       this.prop = 33;
        this.mouseMoving = function() { console.log(this.prop);}

        document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving, true);

 }
4

6 回答 6

25

当事件处理程序被调用时,“this”不再引用“someObj”对象。您需要将“this”捕获到 mouseMoving 函数将捕获的局部变量中。

var someObj = function someObj(){
    this.prop = 33;
    var self = this;
    this.mouseMoving = function() { console.log(self.prop);}

    document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving, true);
}

我假设 "someObj 是一个构造函数,即打算用 as 调用new someObj(),否则 "this" 将是全局范围。

“this”关键字在 JavaScript 中可能会让人感到困惑,因为它的工作方式与其他语言不同。要记住的关键是它在调用函数绑定到调用对象,而不是在创建函数时。

于 2009-07-04T04:44:22.803 回答
12

javascript 内置的 Function.prototype.bind() 就是为此目的而设计的。
例如:

var someObj = function someObj(){
       this.prop = 33;
        this.mouseMoving = function() { console.log(this.prop);}

        document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving.bind(this),true);

 }

更多关于绑定方法的信息:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

否则,您必须将对象 someObj 的引用传递给元素并在行中使用该引用:

console.log(this.referenceToObject.prop); //this references the DOM element in an event.
于 2009-07-04T04:44:39.883 回答
6

来自Douglas Crockford的JavaScript: The Good Parts的第 4.3 节:

调用函数会暂停当前函数的执行,将控制和参数传递给新函数。除了声明的参数外,每个函数还接收两个附加参数:this 和 arguments。this参数在面向对象编程中非常重要,其值由调用模式决定。JavaScript 中有四种调用模式:方法调用模式、函数调用模式、构造函数调用模式和应用调用模式。模式的不同在于如何初始化奖金参数。

Crockford 继续解释每个模式中“this”的绑定,如下所示:

方法调用模式: 当函数作为对象的属性存储时,我们称其为方法。当一个方法被调用时, this 被绑定到那个对象。

函数调用模式: 当使用此模式调用函数时, this 绑定到全局对象。这是语言设计中的一个错误。

构造函数调用模式: 如果使用 new 前缀调用函数,则将创建一个新对象,并带有指向函数原型成员值的隐藏链接,并且 this 将绑定到该新对象。

Apply 调用模式: apply 方法让我们可以构造一个参数数组来调用一个函数。它还允许我们选择 this 的值。apply 方法有两个参数。第一个是应该绑定到 this 的值。第二个是参数数组。

于 2009-07-04T06:02:59.700 回答
3

您可以使用名为“me”的变量,以避免与全局 JavaScript 变量“self”发生冲突:

function someObj() {
  var me = this;
  this.prop = 33;

  this.mouseMoving = function() {
    alert(me.prop);
  }

  document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving, true);
}
于 2014-07-01T15:16:59.907 回答
3

首先,您需要了解“this”在 JavaScript 中的工作原理。'this' 关键字在 C# 或 JAVA 等其他语言中的行为方式不同。阅读以下帖子以了解更多信息,

JavaScript 中“this”关键字行为的基本原理是什么?

一旦您理解了这一点,正如 Matthew 在他的代码中所概述的,您可以保存对“this”的引用并在 mouseMoving 函数中使用该引用。

虽然总的来说,我建议您使用 JavaScript 框架(例如 jQuery、YUI、MooTools)来为您解决这些问题。例如,在 Internet Explorer 中,您使用 addEvent 来附加事件,而不是 addEventListenr。

于 2009-07-04T05:03:27.903 回答
0

您的函数声明中有一些拼写错误。

您的 prop 变量也被定义为“公共”“可见”成员(通过使用 this.prop),这样做会迫使您从外部函数存储this的引用(实际上是对对象实例的引用),作为函数的“私有”成员(使用 var)来访问创建对象的实例并读取“公共”道具成员。

您有一些替代方法来重写此代码:

function someObj (){
    var self = this;
    this.prop = 33;
    this.mouseMoving = function() { alert(self.prop);} // You access the current
                                                       // instance, stored in *self*
                                                       // since *this*, inside the 
                                                       // function, is in another 
                                                       // context.
    //...
}

var mySomeObj = new someObj(); // Object instantiation

或者你可以:

function someObj (){
    var prop = 33;
    this.mouseMoving = function() { alert(prop);} 

    //...
}
var mySomeObj = new someObj(); // Object instantiation

用var声明的变量可以访问在主要构造函数内部声明的函数,这个特性被称为Closures

于 2009-07-04T05:03:10.150 回答