2009-10-16 72 views
4

我是OOP Javascript的新手,并且在this关键字和事件中遇到问题。我想要实现的是:我有多个DOM对象,并且不仅希望将一个公共事件绑定到它们,还要保留一些有关全局容器中前述对象的数据(以提高运行时性能)。Javascript:将OOP方法附加到事件和'this'关键字

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

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); 

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

问题:如何访问JS类实例initscroll方法和窗口元素

它并不一定是通过this关键字,我知道,但我还没有拿出任何东西。

P.S.

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

回答

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() 
}); 

这叫做closure

+0

哇,这么多答案,我不知所措,谢谢大家。无论如何,一个方法到底会如何定义呢? (愚蠢的问题,对不起) – raveren 2009-10-16 14:09:39

+0

@Raveren:这是一个很大的问题。此代码示例是crockford称为“特权”成员声明的示例。请参阅http://www.crockford.com/javascript/private.html这实际上是JavaScript中OOP的高级方法。如果您想从JavaScript中定义类的基本入手开始,请从以下网址开始:http://mckoss.com/jscript/object.htm – 2009-10-16 14:42:14

0

您可以使用封为:

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

    function init() { 
     addEvent(window,'scroll',self.scroll); 
    } 
} 
+2

a)那不是封闭。 b)这仍然不起作用。 – 2009-10-16 13:43:44

+0

它不起作用,因为我只是复制'函数init()',并不使它'this.init = function()'。你为什么认为这不是封闭? – 2009-10-16 15:13:39

+0

同样重要的是如何使用这个类。正确的代码是'var myClassInstance = new ClassThatDoesSomething(); myClassInstance.init();” – 2009-10-16 15:17:12

2
function MyConstructor() { 
    this.foo = "bar"; 
    var me = this; 
    function myClosure() { 
     doSomethingWith(me.foo); 
    } 
} 
-1

这招应该工作:

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

那么那些有问题的方法中,你可以使用'This'

希望这会有所帮助。

+0

不,它不起作用。 – slikts 2009-10-16 13:39:51

+0

'this.This = this'。我甚至无法把我的头包裹在里面。 – 2009-10-16 13:58:58

1

this直到执行该功能才被确定。当附加一个事件监听器时,你传递一个函数,它不带有作用域。因此,在指定的事件中,函数运行在window的范围内,这意味着this将等于window。要强制执行特定的范围,你可以使用的技巧,比如创建了一个新变量等于this,如:

var that = this; 
... 
addEvent(window,'scroll', function() { 
    that.scroll() 
}); 
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); 
} 
1

添加一个方法的函数原型,允许你到任何函数绑定到任何对象:

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); 
}