下面我在Javascript中创建一个对象。在构造函数中,我正在设置一个事件监听器。问题是当事件被触发时,找不到this.prop,并且未定义打印输出。我该如何解决这个问题?
var someObj = function someObj(){
this.prop = 33;
this.mouseMoving = function() { console.log(this.prop);}
document.getElementById("someDiv").addEventListener('mousemove', this.mouseMoving, true);
}
答案 0 :(得分:21)
当调用事件处理程序时,“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中可能会造成混淆,因为它与其他语言的工作方式不同。要记住的关键是它在调用函数时绑定到调用对象,而不是在创建函数时绑定。
答案 1 :(得分:8)
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.
答案 2 :(得分:5)
来自 JavaScript:好的部分的第4.3节 Douglas Crockford :
调用函数暂停 执行当前功能, 将控制和参数传递给 新功能。除了 声明参数,每个函数 接收另外两个参数: 这和争论。这个参数 在面向对象方面非常重要 编程,它的价值在于 由调用模式决定。 有四种调用模式 在JavaScript中:方法调用 模式,函数调用 模式,构造函数调用 模式和应用调用 图案。模式因人而异 这是奖金参数 初始化。
Crockford继续解释每种模式中“this”的绑定,如下所示:
方法调用模式: 当函数存储为对象的属性时,我们将其称为方法。调用方法时,它绑定到该对象。
函数调用模式: 使用此模式调用函数时,它将绑定到全局对象。这是语言设计中的一个错误。
构造函数调用模式: 如果使用新前缀调用函数,则将创建一个新对象,其中隐藏了指向函数原型成员值的链接,并且这将绑定到该新对象。
应用调用模式: apply方法允许我们构造一个用于调用函数的参数数组。它还让我们选择了它的价值。 apply方法有两个参数。第一个是应该绑定的值。第二个是参数数组。
答案 3 :(得分:3)
首先,您需要了解'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。
答案 4 :(得分: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);
}
答案 5 :(得分:0)
你的功能声明上有一些拼写错误。
您的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。