4

我是 OOP Javascript 的新手,在this关键字和事件方面遇到了麻烦。

我想要实现的是:我有多个 DOM 对象,并且不仅希望将公共事件绑定到它们,而且希望将有关上述对象的一些数据保存在全局容器中(以提高运行时性能)。

所以我所做的基本上是这样的:

function ClassThatDoesSomething() {
    /* keeps node ids for processing in this.init */
    this.nodes = new Array();

    /* keeps processed node data for fast access */
    this.nodeData = new Array();

    this.sthAddNodes = function(/* ids */) {
        /* appends node ids to local variable (this.nodeData) */
    }

    function init() {
        /* gathers data from all nodes that were 
           added before and stores it in this.nodeData */

        /* here, unsurprisingly, 'this' references the window element*/

        addEvent(window,'scroll',this.scroll);
    }

    function scroll() {
        /* do stuff when user scrolls the page */

        /* 'this' references the window element here too */
    }
    addEvent(window,'load',this.init);
}

稍后,在文档正文中,我可以添加以下内容:

var Ctds = new ClassThatDoesSomething();

更进一步,通过以下方式添加 DOM 元素:

Ctds.addNodes(ids);

不需要进一步的实现代码。

问题:如何在and方法中访问JS 类实例而不是window 元素initscroll

我知道,它不必通过this关键字,但我仍然没有想出任何东西。

附言

  • addEvent是一个非常基本的附加事件的功能,它只是对 IE/Fx 友好,没有其他功能。
  • 我正在编写的代码已经是功能性的,但是在程序形式上,我只是想对它进行 OOP。
  • 作为一个小问题,我以某种方式得到了这样的印象,即在 javascript 中不鼓励 getter/setter 方法,如果我使用它们可以吗?
4

7 回答 7

10

我注意到的一件事是实例上的方法既不是init也不是。scroll

所以你只需要添加init而不是this.init加载事件:

addEvent(window,'load',init); // No "this." needed

同样:

addEvent(window,'scroll',scroll);

如果您决定将它们移动到类(例如this.scrollthis.init),您可以保存一个引用this并在传递给的匿名函数中引用它addEvent

var self = this;

this.init = function() {
    addEvent(window, 'scroll', function() {
        self.scroll()
    })
};

this.scroll = function() { /* ... */ };

addEvent(window,'load',function() {
    self.init()
});

这称为闭包

于 2009-10-16T13:34:30.427 回答
2
function MyConstructor() {
    this.foo = "bar";
    var me = this;
    function myClosure() {
        doSomethingWith(me.foo);
    }
}
于 2009-10-16T13:36:27.920 回答
1

this直到函数执行才确定。附加事件侦听器时,您正在传递一个函数,该函数不带有它的作用域。因此,在指定事件上,函数在 的范围内运行window,这意味着this将等于window。要强制在特定范围内执行,您可以使用诸如创建一个新变量等技巧来 equal this,例如:

var that = this;
...
addEvent(window,'scroll', function() {
    that.scroll()
});
于 2009-10-16T13:45:11.273 回答
1

向 Function 原型添加一个方法,允许您将任何函数绑定到任何对象:

Function.prototype.bind = function(object) {
   var __method = this;
   return function() {
      return __method.apply(object, arguments);
   };
};

在实例中声明您的事件处理程序(保持整洁):

function ClassThatDoesSomething() {

  this.events = {
    init: ClassThatDoesSomething.init.bind(this),
    scroll: ClassThatDoesSomething.scroll.bind(this),
    etc: ClassThatDoesSomething.etc.bind(this)
  };
  ...
}

现在,每当您引用您的事件时,它们都会自动绑定到类实例。例如:

function init() {
  addEvent(window,'scroll',ClassThatDoesSomething.events.scroll);
}
于 2009-10-16T13:52:37.000 回答
0

您可以为此使用闭包:

function ClassThatDoesSomething() {
    var self=this;
    // ...

    function init() {
        addEvent(window,'scroll',self.scroll);
    }
}
于 2009-10-16T13:34:00.990 回答
0

做这个:

var ClassThatDoesSomething = function() {
    /* keeps node ids for processing in this.init */
    this.nodes = new Array();

    /* keeps processed node data for fast access */
    this.nodeData = new Array();
}

ClassThatDoesSomething.prototype.sthAddNodes = function(/* ids */) {
        /* appends node ids to local variable (this.nodeData) */
    }
}

ClassThatDoesSomething.prototype.init = function() {
        /* gathers data from all nodes that were 
           added before and stores it in this.nodeData */

        /* here, unsurprisingly, 'this' references the window element*/

        addEvent(window,'scroll',this.scroll);
    }
}
ClassThatDoesSomething.prototype.scroll = function() {
        /* do stuff when user scrolls the page */

        /* 'this' references the window element here too */
    }
    addEvent(window,'load',this.init);
}
于 2009-10-16T13:45:51.600 回答
-1

这个技巧应该有效:

function ClassThatDoesSomething() {
...
    this.This = this;
...
}

然后在这些有问题的方法中,您可以使用'This'.

希望这可以帮助。

于 2009-10-16T13:36:35.960 回答