我最近开始编写JavaScript并认为一切都会很好...... 那么今天我遇到了一个我自己无法解决的问题。 我的教程/学习项目有一个名为model的类。在这个类中有几个私有变量和一个公共变量。此变量的类型为CustomEvent:
function Model(){
/**
* Array in which the questions are stored
*/
var questions=new Array();
var db;
var valuesSplit="*";
var tableName="quests";
this.myEvent=new CustomEvent("my event");
因此,您可以看到“myEvent”是公开的,可以从外部调用。在这种情况下,它是一个可以订阅的事件(这是在这个类之外由其他想要监听的对象完成的)并且可以被触发(这在同一个类中完成)。这是我的问题。 如何在模型类中访问myEvent?
我试过了:
this.myEvent.fire()
和
myEvent.fire()
但我总是得到“myEvent未定义”。
答案 0 :(得分:6)
可能首先要说的是:JavaScript没有类。你越早停止思考“JavaScript类”,你就越好。 :-) JavaScript有OOP,但没有类的类。您的Model
函数称为构造函数。
您可以从任何引用myEvent
创建的对象的代码中访问new Model
,其中包含构造函数中的代码(通过this
- 例如,您的方式设置它)和任何用this
调用的函数引用该对象(当然,通过someObjReference.myEvent
“外部”)。
所以this.myEvent.fire()
可能就是您想要的,但您调用它的代码没有正确的this
值。这是因为在JavaScript中,this
完全由如何调用函数控制,而不是,其中函数被定义,就像在其他一些语言中一样。有关详细信息,请参阅我的博客文章Mythical methods和You must remember this
,但我在下面做了一些有些截断的讨论。
以下是使用所有实例共享的有用方法设置构造函数的相当标准方法的示例:
function Foo() {
this.myEvent = new CustomEvent("my event");
}
Foo.prototype.bar = function() {
this.myEvent.fire();
};
// Usage:
var f = new Foo();
f.bar(); // Fires the event indirectly, via the code in `bar`
f.myEvent.fire(); // Fires it directly
请注意,只有在bar
调用this
时才会引用具有myEvent
属性的对象。通过将bar
完全设置为其他内容,可以轻松调用this
:
document.getElementById("someID").onclick = f.bar;
点击发生时,bar
函数会被调用,但this
不会引用通过Model
创建的对象。 (它将引用id为“someID”的元素。)所以bar
中的这一行
this.myEvent.fire();
......会失败。
如果您习惯使用基于类的语言,您可以看到它与Java,C#或C ++完全不同。在这些语言中,this
内的bar
将始终引用通过new Model
创建的对象。不是那么JavaScript,这既尴尬又强大。
这种函数的灵活性(不受任何特定对象的约束)是在JavaScript中习惯并利用的最重要的事情之一。另一个是函数闭包的功能,它功能强大但是not complicated。
因此,如果this
是根据函数的调用方式设置的,那么你如何做到这一点?有两种方法:
通过从与调用相同的表达式中的对象属性引用该函数来调用该函数。这是一种尴尬的说法:
var f = new Foo();
f.bar(); // <== The key bit
f["bar"](); // <== Also works
表达式f.bar()
执行两项交互操作:它首先要检索bar
引用的对象的属性f
,并获取该属性的值(即功能参考)。然后它调用该函数(因为()
)。 JavaScript的工作方式,因为您在同一个整体表达式中执行了这两项操作,解释器会在为this
调用f
期间将bar
设置为var f = new Foo();
var b = f.bar;
b(); // <== Different!
。但请注意这一关键区别:
bar
现在调用this
函数时,f
将不设置为window
(它将被设置为全局对象,即浏览器上的call
,因为我们已将属性检索与函数调用分开。
或者,您可以使用JavaScript函数对象的内置功能,apply
和call
函数。 apply
和var f = new Foo();
f.bar(1, 2): // <== Calls `bar` with `this` === `f` and passing in
// the arguments 1 and 2
var b = f.bar;
b.call(f, 1, 2); // <== Does the same thing as f.bar(1, 2)
var args = [1, 2];
b.apply(f, args); // <== Does the same thing as f.bar(1, 2)
完成相同的事情,它们之间的唯一区别是你如何提供函数的参数。例如:
call
例如,apply
和this
允许您在调用函数时设置call
应明确的内容。它们之间的唯一区别是call
接受参数以将函数作为apply
的进一步参数,而{{1}}接受它们作为数组。
答案 1 :(得分:1)
如果您想在myEvent
的非公开功能中使用Model
,则必须创建对未使用myEvent
的{{1}}的其他引用您的模型的参考。因为另一个函数中的this
不是this
函数中的Model
。绕过此问题的最简单方法是在Model
中定义新变量:
var that = this;
然后你可以打电话给myEvent
,如:
that.myEvent
答案 2 :(得分:0)
myEvent
成员应该在内部和外部都可见。对象的外部范围:
function Model(){
this.myEvent = 'some value';
this.canAccessEvent = function(){
return 'myEvent' in this;
}
}
var m = new Model();
// access from outside :
alert(m.myEvent);
// access from inside :
alert('Model can access the even? ' + m.canAccessEvent());
但是,您的new CustomEvent
函数很可能不存在或者未返回有效对象,导致myEvent
变量为undefined
。我建议你将一些其他值归因于myEvent
属性并查看它是否已定义。如果已定义,则问题出在您的CustomEvent
函数中。