Javascript:如何访问同一个类中的公共变量?

bat*_*ope 2 javascript oop class

我最近开始编写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");
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到"myEvent"是公开的,可以从外部调用.在这种情况下,它是一个可以订阅的事件(这是在这个类之外由其他想要监听的对象完成的)并且可以被触发(这在同一个类中完成).这是我的问题.如何在模型类中访问myEvent?

我试过了:

    this.myEvent.fire()
Run Code Online (Sandbox Code Playgroud)

和:

    myEvent.fire()
Run Code Online (Sandbox Code Playgroud)

但我总是得到"myEvent未定义".

T.J*_*der 6

可能首先要说的是:JavaScript没有类.你越早停止思考"JavaScript类",你就越好.:-) JavaScript有OOP,但没有类的类.您的Model函数称为构造函数.

您可以myEvent从任何引用创建对象的代码访问new Model,其中包括构造函数中的代码(通过this - 例如,您设置它的方式)以及通过this引用该对象调用的任何函数(或者,当然,"外部"通过someObjReference.myEvent).

所以可能this.myEvent.fire()是你想要的,但是你调用它的代码没有正确的this价值.这是因为在JavaScript中,this完全由函数的调用方式控制,而不是像其他语言那样定义函数的位置.请参阅我的博客文章神话方法 ,你必须记住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
Run Code Online (Sandbox Code Playgroud)

请注意,仅当bar通过this引用具有myEvent属性的对象调用时才有效.bar使用thisset完全调用其他东西很容易:

document.getElementById("someID").onclick = f.bar;
Run Code Online (Sandbox Code Playgroud)

当点击发生时,bar函数被调用,但this并非是指通过创建的对象Model.(它将引用id为"someID"的元素.)所以这一行bar

this.myEvent.fire();
Run Code Online (Sandbox Code Playgroud)

...将失败.

如果您已经习惯了基于类的语言,那么您可以看到它与Java,C#或C++完全不同.在那些语言中,this内部bar将始终引用通过创建的对象new Model.不是那么JavaScript,这既尴尬又强大.

函数的这种灵活性(不受任何特定对象约束)是在JavaScript中习惯并利用的最重要的事情之一.另一个是函数是闭包的方式,它功能强大但并不复杂.

因此,如果this根据函数的调用方式设置,那么你是如何做到的?有两种方法:

  1. 通过从与调用相同的表达式中的对象属性引用该函数来调用该函数.这是一个尴尬的说法:

    var f = new Foo();
    f.bar();    // <== The key bit
    f["bar"](); // <== Also works
    
    Run Code Online (Sandbox Code Playgroud)

    表达式f.bar()做了两件事,它们相互作用:它首先做的是检索bar引用的对象的属性f,并获取该属性的值(这是一个函数引用).然后它调用该函数(因为()).JavaScript的工作,因为你在相同的整体表现做这两件事情的方式,解释集thisf调用过程中bar为您服务.但请注意这一关键区别:

    var f = new Foo();
    var b = f.bar;
    b(); // <== Different!
    
    Run Code Online (Sandbox Code Playgroud)

    现在,当bar函数被调用时,this不会被设置为f(它将被设置为全局对象,这是window在浏览器上),因为我们已将属性检索与函数调用分开.

  2. 或者,您可以使用JavaScript函数对象的内置功能,它们callapply函数.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)
    
    Run Code Online (Sandbox Code Playgroud)

    例如,call并且apply允许你设置什么this应该明确,当你调用该函数.它们之间的唯一区别是call接受参数以将函数作为进一步的参数call,并将apply它们作为数组接受.