在命名空间对象或闭包中保留事件处理程序代码的位置?

时间:2009-06-18 21:32:42

标签: javascript

在过去的几年里,我一直使用YUI支持的JavaScript名称空间作为格式化JavaScript代码的默认方式。

总而言之,它适用于更复杂的环境,在这种环境中,许多Web小部件可能会在不同时间粘在一起。

直到最近,我几乎总是在HTML中通过从名称间隔对象本身调用处理程序来使用添加的事件处理程序。

我最近一直在使用JQuery,并且已经在ready函数中设置了处理程序,而不是在HTML中。

正如我越来越多地认为JQuery ready函数的闭包似乎取代了名称空间对象。

我现在最终得到的结果(至少对于一个窗口小部件/工具类型页面)是一个名称空间对象,它主要处理保存数据和一堆关闭的事件处理程序,我访问名称空间对象以用于特定于数据的目的。

我的问题是,处理闭包的最佳实践与Name空间对象有什么关系,特别是与事件处理程序有关?

或者,类似地,设置事件处理程序的最佳实践是什么,如果它们“重量级”并且自己处理处理,或者交给更多类似代码的库。

就个人来说,跟踪许多独立的“重量级”事件处理程序的流程更加困难。

1 个答案:

答案 0 :(得分:2)

这是一个非常主观的问题。话虽这么说,我会尽力给出我认为每种方法的利弊。

命名空间对象:

yourNamespace.events.someClickHandler = function(event) {...}
$(function() {
  $("#someElement").click(yourNamespace.events.someClickHandler);
}

这种方法的第一个“缺点”之一就是将事件处理程序与它的连接分开。您可以通过在定义每个事件之后挂钩它来避免这种情况(就像我在上面的示例中所做的那样),但是在整个代码中你会得到大量的“$(function(){”行。

此样式的另一个“con”是事件处理程序的长名称(例如“yourNamespace.events.someClickHandler”)。您可以使用别名:

var events = yourNamespace.events;
$("#someElement").click(events.someClickHandler);

和更短的命名空间名称可以缓解这种情况,但实际上没有办法解决它。

所有这些缺点,为什么有人会使用命名空间模式?那么,它的一个“专业”是事件是可访问的。假设(出于调试目的),您希望记录传递给Click处理程序的事件对象。使用Firebug,您可以执行以下操作:

var oldHandler = yourNamespace.events.someClickHandler;
var newHandler = function(e) {console.log(e); oldHandler(e);}
$("#someElement").unbind("click");
$("#someElement").click(yourNamespace.events.someClickHandler);

并且,甚至无需刷新页面,您都可以记录您的活动。

同样,这种风格还有另一种可重用性。如果你想创建一个类似于旧的点击处理程序,但也做x,y和z,你可以这样做:

yourNamespace.events.advancedClickHandler = function(event) {
  yourNamespace.events.someClickHandler(e);
  x(); y(); z();
}

现在相反,我们有“封闭”风格(我更喜欢称之为“匿名功能”风格)。

$(function() {
  $("#someElement").click(function(event) {...});
}

它显然更简洁,处理程序的定义与它可以达到的连接一样接近,我认为它甚至使用了少量的内存,因为没有变量引用。但是,你将无法进行任何实时调试,你将无法在其他任何地方挂起该处理程序,或者在一些新的处理程序或类似的东西中扩展它,因为你的处理程序目前只存在当你把它连接起来时。

所以,希望这会有所帮助。根据我的经验,命名空间对象样式通常是首选方法,尤其是JS项目的核心/严肃程度。但它肯定有一些缺点;在这个时候,确实没有完美的(即完全清洁/可重复使用)方式来连接JS中的事件。