从 Javascript 中的事件侦听器调用访问对象的属性

Posted

技术标签:

【中文标题】从 Javascript 中的事件侦听器调用访问对象的属性【英文标题】:Accessing an object's property from an event listener call in Javascript 【发布时间】:2010-11-08 01:34:13 【问题描述】:

下面我正在用 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);

 

【问题讨论】:

【参考方案1】:

您可以使用名为“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);

【讨论】:

【参考方案2】:

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.

【讨论】:

谢谢!我搜索了将近一个小时才找到这个。我知道这是可以做到的。这似乎是一种失传的技术。 这是干净的解决方案,应该是公认的答案。【参考方案3】:

来自 Douglas CrockfordJavaScript: The Good Parts 的第 4.3 节:

调用函数会挂起 执行当前函数, 将控制和参数传递给 新功能。除了 声明的参数,每个函数 接收两个附加参数: 这和论点。这个参数 在面向对象中非常重要 编程,其值为 由调用模式决定。 有四种调用模式 在 JavaScript 中:方法调用 模式,函数调用 模式,构造函数调用 模式和应用调用 图案。模式的不同之处在于 奖金参数这是 初始化。

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

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

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

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

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

【讨论】:

【参考方案4】:

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

What is the rationale for the behavior of the 'this' keyword in JavaScript?

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

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

【讨论】:

感谢您发布该链接。我一直在寻找答案,但找不到。 没问题。我认为告诉新的 JavaScript 用户“this”是如何工作的很重要。除非他们理解“this”,否则我认为他们无法编写正确的 JavaScript 或调试。【参考方案5】:

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

您的 prop 变量也被定义为 "public""visible" 成员(通过使用 this.prop),这样做会强制您存储this 从外部函数(即实际上是对对象实例的引用),作为函数的一个"private" 成员(使用var)来获取对实例的访问创建的对象并读取 "public" prop 成员。

你有一些替代方法来重写这段代码:

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。

【讨论】:

【参考方案6】:

当事件处理程序被调用时,“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 是一个构造函数,即打算以new someObj() 调用,否则“this”将是全局范围。

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

【讨论】:

var 名称可能不应该是“self”,因为它是一个预定义的 JS 变量。 有一个全局“self”变量,但不存在冲突,因为局部变量会覆盖全局变量。如果它令人困惑,你可以使用其他东西。有些人使用“that”,但我发现“this”和“that”是同一个对象是违反直觉的。

以上是关于从 Javascript 中的事件侦听器调用访问对象的属性的主要内容,如果未能解决你的问题,请参考以下文章

Javascript事件奇怪的行为,removeEventListener无法正常工作

学习javascript中的事件——事件流

JavaScript中的事件

使用 Worklight 从原生 Android 代码触发 javascript 事件侦听器

在 JavaScript 中清除事件处理程序有多重要? [复制]

JS的事件流的概念(重点)