如何从Javascript类方法引用函数?

时间:2011-01-03 17:02:24

标签: javascript reference deep-linking

我使用SWFAddress深度链接我的网站(link to SWFAddress)。我喜欢将代码分解为类,因此我有一个类似于此的主结构:

function SomeClass() {
    //this adds the this.handleChange() function to the
    //SWFAddress event listener
    this.initializeSWFA = function() {
        //SWFAddress variable is instantiated in SWFAddress javascript file
        //so I can use it here
        SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);
    }

    //SWFAddress suppose to call this function
    this.handleChange= function(evt) {
    //some code here
    }

}

//instantiate the SomeClass
var someVar = new SomeClass();
someVar.initializeSWFA();

这一行在这里不起作用:

SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);

我尝试将其更改为:

SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange());

var self = this;
SWFAddress.addEventListener(SWFAddressEvent.CHANGE, self.handleChange);

这些也不起作用。

那么如何在这样的情况下从类中引用javascript函数?如果函数handleChange在类之外,我可以编写函数的名称。

提前谢谢

修改

首先,谢谢你的所有答案。我仍然试图想象这一切在Javascript中是如何工作的。我不习惯像Javascript这样的面向对象模型。

这是现在的解决方案。我仍然无法弄清楚如何在Javascript中很好地做到这一点,但这个解决方案的工作原理。我试图实现ehudokai建议的解决方案(谢谢),但无法使其正常工作。

function SomeClass() {
    //this adds the this.handleChange() function to the
    //SWFAddress event listener
    this.initializeSWFA = function() {
        //SWFAddress variable is instantiated in SWFAddress javascript file
        //so I can use it here
        SWFAddress.addEventListener(SWFAddressEvent.CHANGE, someFunc);
    }

    //SWFAddress suppose to call this function
    this.handleChange= function(evt) {
    //some code here
    }

}

//instantiate the SomeClass
var someVar = new SomeClass();

function someFunc(evt) {
    someVar.handleChange(evt);
}

someVar.initializeSWFA();

我不喜欢这个,因为这涉及定义一个额外的函数,所以需要额外的空间如果有人想出如何从Javascript对象向SWFAddress EventListener添加方法,请帮助我。

3 个答案:

答案 0 :(得分:7)

您的班级结构完全有效。但是,如果您的handleChange()函数使用this关键字,期望someVar,那么这就是您的问题所在。

这就是:

  1. SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);正确引用了类中的处理函数。 SWFAddress缓存该函数到某个变量f,直到调度该事件为止。
  2. 调度事件时,SWFAddress会调用f。虽然保留了对函数的引用,但对上下文的引用或this不是。因此this默认为window
  3. 要解决这个问题,您只需要使用一个匿名函数来捕获类范围内的变量。您可以使用此匿名函数中的正确上下文调用处理程序:

    function SomeClass() {
        this.initializeSWFA = function() {
            // Save a reference to the object here
            var me = this;
    
            // Wrap handler in anonymous function
            SWFAddress.addEventListener(SWFAddressEvent.CHANGE, function (evt) {
                me.handleChange(evt);
            });
        }
    
        //SWFAddress suppose to call this function
        this.handleChange= function(evt) {
        //some code here
        }
    
    }
    

    按照OP的要求解释this

    可以用不同的方式解释this关键字:首先阅读this article about scope,然后阅读this article about object-oriented javascript

    我也想提出我的快速推理,你可能会觉得有帮助。请记住,Javascript没有像Java这样的语言的“类”。在这些语言中,类的“方法”仅属于该类(或可以继承)。然而,在javascript中,只有对象和对象属性才会发生在函数中。这些函数是自由代理 - 它们属于属于一个或另一个对象,就像字符串或数字一样。例如:

    var a = {
        myMethod: function () {...}
    };
    
    var b = {};
    b.myMethod = a.myMethod;
    

    在这种情况下,myMethod属于哪个对象?没有答案,可以是ab。因此a.myMethod只是对函数的引用,与“上下文”或父对象不相关。因此this没有任何意义,除非使用a.myMethod()b.myMethod()明确调用,因此在以任何其他方式调用时默认为window。出于同样的原因,javascript中没有parentsuper关键字。

答案 1 :(得分:1)

我担心我无法确定您的问题,但我会说这与您使用SWFAddress有关。您构建SomeClass的方式及其方法是完全有效的,与此处的其他答案相反。

进一步澄清miki(现已删除)的问题来自另一个答案,关于this如何运作:

this的行为方式有两种情况;使用new - 运算符调用的常规函数​​和函数。

对于常规函数调用,this引用点左侧的对象(松散地说):例如,在编写someVar.initializeSWFA()时,this将引用{{1} }}。调用不带点的函数时,someVar将引用全局对象。可以将一个函数从一个对象分配给另一个对象,因此this将被移位,如下所示:

this

然后,当使用var someVar = new SomeClass(); var anotherVar = {}; anotherVar.aNewNameForTheSameFunction = someVar.initializeSWFA; anotherVar.aNewNameForTheSameFunction(); // inside of this call to initializeSWFA, "this" will be "anotherVar" - 运算符调用时,我们也会遇到这种情况。在这种情况下,new将为您创建一个新对象,new将引用该对象。

通过使用this - 函数,还有一些方法可以使用显式设置this来调用函数:

call

这将调用函数initializeSWFA var someVar = new SomeClass(); var aNumber = 5; someVar.initializeSWFA.call(aNumber, arg1, arg2, ..., argN); 作为aNumber,并将参数thisarg1等传递给它。请注意arg2已被采用在那种情况下不合时宜。

答案 2 :(得分:1)

我认为最好的办法是停止将SomeClass视为一个类。

Javascript没有课程。它使用原型继承。我不会在这里深入探讨。基本上它意味着你只有对象。如果你想创建另一个像第一个对象,你可以使用Object.prototype属性来做到这一点。

所以,如果你想做你想做的事情。 (假设SWFAddress与大多数javascript一样),请执行以下操作。

var someVar = {  // (using object notation)
    initializeSWFA : function(){
        SWFAddress.addEventListener(SWFAddressEvent.CHANG, this.handleChange);
    },
    handleChange : function(){
        // your code here
    }
}

此时你可以直接调用someVar

someVar.initializeSWFA();

如果您想要创建一个可以继承其他对象的对象,请尝试以下操作。

var baseObject = function(){};
baseObject.prototype.handleChange = function(){
    // your code here
}
baseObject.prototype.initializeSWFA = function(){
    SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);
}

var someVar = new baseObject();
someVar.initializeSWFA();

new运算符只是创建一个新对象,该对象继承了指定对象的.prototype。

希望有所帮助。