8

我使用 SWFAddress 深度链接我的网站(链接到 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 is supposed 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 添加方法,则需要额外的空间。请帮帮我。

4

3 回答 3

12

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

这就是发生的事情:

  1. SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);正确引用类中的处理函数。SWFAddress 将该函数缓存到某个变量f,直到分派事件。
  2. 当事件被调度时, SWFAddress 调用f. 虽然保留了对函数的引用,但不会保留对上下文的引用 or this。因此this默认为window.

为了解决这个问题,您只需要使用一个匿名函数来捕获类范围内的变量。您可以在此匿名函数中使用正确的上下文调用处理程序:

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
    }

}

##this按照OP的要求对 的解释:##

this关键字可以用不同的方式解释:首先阅读这篇关于范围的文章,然后阅读这篇关于面向对象的 JavaScript 的文章

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

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

var b = {};
b.myMethod = a.myMethod;

myMethod在这种情况下,属于哪个对象?没有答案;它可以是ab。因此a.myMethod只是对函数的引用,与“上下文”或父对象无关。因此,除非使用or显式调用this它,否则没有任何意义,因此默认为以任何其他方式调用时。出于同样的原因,JavaScript 中没有or关键字这样的东西。a.myMethod()b.myMethod()windowparentsuper

于 2011-01-04T07:39:23.827 回答
2

我认为最好的办法是停止将 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的新对象。

于 2011-01-03T17:57:36.760 回答
1

恐怕我无法确定您的问题,但我会说这与您使用SWFAddress. 您构建的方式SomeClass及其方法是完全有效的,这与这里的其他一些答案所说的相反。

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

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

对于常规函数调用,this指的是点左侧的对象(松散地说):例如,在编写 时someVar.initializeSWFA()this将指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-operator 调用的情况。在这种情况下,new将为您创建一个新对象并this引用该对象。

还有一些方法可以this通过使用call-function 来调用具有显式 set 的函数:

var someVar = new SomeClass();
var aNumber = 5;
someVar.initializeSWFA.call(aNumber, arg1, arg2, ..., argN);

aNumber这将使用as调用函数 initializeSWFAthis并将参数传递给它arg1arg2等等。注意someVar在这种情况下从等式中取出。

于 2011-01-03T17:20:32.263 回答