我最近已经对一些已经维护了两年的旧代码进行了修改。
作为使用对话框样式面板的YAHOO YUI 2.2(是的,那很旧)的脚本的一部分,我有一个函数来监听给定面板集中3个按钮的单击事件:
addFooListeners = function (panelType) {
YAHOO.util.Event.addListener("show" + panelType, "click", showFoo, eval(ns + ".panel_" + panelType), true);
YAHOO.util.Event.addListener("hide" + panelType, "click", hideFoo, eval(ns + ".panel_" + panelType), true);
YAHOO.util.Event.addListener("commit" + panelType, "click", commitFoo, eval(ns + ".panel_" + panelType), true);
}
这段代码是许多面板/对话框具有几乎相同的行为的结果。
对于这一轮开发,我已经需要添加不时做事的功能,因此我添加了一个对象
overrides
,它使我可以将show
,hide
和commit
操作指向其他位置。我想出了以下内容:addFooListeners = function (panelType, overrides) {
var handlers = {
show: ( overrides != null ? ( overrides.show != null ? overrides.show : showFoo ) : showFoo ),
hide: ( overrides != null ? ( overrides.hide != null ? overrides.hide : hideFoo ) : hideFoo ),
commit: ( overrides != null ? ( overrides.commit != null ? overrides.commit : commitFoo ) : commitFoo )
}
YAHOO.util.Event.addListener("show" + panelType, "click", handlers.show, eval(ns + ".panel_" + panelType), true);
YAHOO.util.Event.addListener("hide" + panelType, "click", handlers.hide, eval(ns + ".panel_" + panelType), true);
YAHOO.util.Event.addListener("commit" + panelType, "click", handlers.commit, eval(ns + ".panel_" + panelType), true);
}
如您所见,我正在强制执行默认行为,除非
overrides
对象中的适当属性设置了另一个函数(命名为或是否有一种更简洁/可读性强的方法来简洁地设置
handlers
对象?在我眼中,嵌套的三元似乎有点杂乱无章,但是像if ( overrides != null ) { ... }
这样的其他方法似乎也很混乱。#1 楼
让我们进行一些修复。首先,这是在JS(Good Waytm)中传递可选(非布尔)参数的方式:addFooListeners = function (panelType, handlers) {
handlers = handlers || {};
handlers.show = handlers.show || showFoo;
handlers.hide = handlers.hide || hideFoo;
handlers.commit = handlers.commit || commitFoo;
以上内容可以使用jQuery以更整洁的方式重写(不确定与
extend
等效的YUI的名称是什么):handlers = $.extend({
show : showFoo,
hide : hideFoo,
commit: commitFoo
}, handlers || {})
现在,对此代码使用eval是犯罪的。假设对象
ns
所指的是module
,则可以代替eval
来执行此操作:YAHOO.util.Event.addListener("show" + panelType, "click", handlers.show, module["panel_" + panelType], true);
YAHOO.util.Event.addListener("hide" + panelType, "click", handlers.hide, module["panel_" + panelType], true);
YAHOO.util.Event.addListener("commit" + panelType, "click", handlers.commit, module["panel_" + panelType], true);
现在,如您所见,您将在类似的方式。您是否想在函数中定义addPanelListener函数?
function addPanelListener (event, panelType, handler) {
YAHOO.util.Event.addListener(event + panelType, "click", handler, module["panel_" + panelType], true);
}
addPanelListener("show" , panelType, handlers.show);
addPanelListener("hide" , panelType, handlers.hide);
addPanelListener("commit", panelType, handlers.commit):
希望对您有所帮助。
评论
\ $ \ begingroup \ $
+1标记将eval标记为犯罪:)我发现“ The Good Way”比jQuery更具可读性。
\ $ \ endgroup \ $
– EricBréchemier
2011年1月31日13:06
\ $ \ begingroup \ $
在我公司使用eval几乎可以保证3个小时与我见面的javascript会议:)
\ $ \ endgroup \ $
–glebm
2011年1月31日在21:25
\ $ \ begingroup \ $
aaah很好的“第一个免费”评价。很像推毒器。每当我在代码中看到该代码时,我都会感到畏缩(尤其是我在此处发布的代码;-)。
\ $ \ endgroup \ $
– LRE
2011年1月31日在21:32
\ $ \ begingroup \ $
@glebm您能详细说明什么使“好方法”成为好方法吗?
\ $ \ endgroup \ $
– LRE
2011年1月31日21:34
\ $ \ begingroup \ $
当然。它易于阅读,不易出错,而且更快。 :)
\ $ \ endgroup \ $
–glebm
2011年1月31日21:36
#2 楼
看来您可以使用&&这样减少三元数:var handlers = {
show: ( overrides != null && overrides.show != null ? overrides.show : showFoo ),
hide: ( overrides != null && overrides.hide != null ? overrides.hide : hideFoo ),
commit: ( overrides != null && overrides.commit != null ? overrides.commit : commitFoo )
}
我对javascript不太熟悉,但是是否需要检查function参数对空?例如,您可以通过执行以下操作来进一步缩短检查时间吗?
show: ( overrides && overrides.show ? overrides.show : showFoo ),
hide: ( overrides && overrides.hide ? overrides.hide : hideFoo ),
// ...
评论
\ $ \ begingroup \ $
一般来说,我认为您不需要对null进行检查是正确的-但是它可以为非null和false,然后将其评估为false(尽管在这种情况下,我认为可以)
\ $ \ endgroup \ $
– LRE
2011年1月31日,0:03
\ $ \ begingroup \ $
Overrides.show看起来可能是布尔值;如果是这样,则需要显式针对null进行测试。
\ $ \ endgroup \ $
– Fred Nurk
2011年1月31日,下午1:36
\ $ \ begingroup \ $
@Fred的目的是传递用于显示,隐藏和提交的函数。如果在此处传递了false,则将使用showFoo()。如果将true传递给了那,那么它将被代替showFoo()并引起进一步的麻烦,所以我想我需要谨慎行事。话虽这么说,但我只会在这些参数中传递一个函数,因此我现在可能会生存下来。
\ $ \ endgroup \ $
– LRE
2011年1月31日,下午1:48
\ $ \ begingroup \ $
可能值得指出的是,&&的使用仅在&&是短路和运算的情况下才有效(对于C派生的语言,但这不是所有语言的安全假设)。
\ $ \ endgroup \ $
–托德·雷曼(Todd Lehman)
2012年1月22日上午8:01
\ $ \ begingroup \ $
甚至可以更短:show:覆盖&& overlay.show || showFoo
\ $ \ endgroup \ $
–一些
2012年8月13日在22:51
#3 楼
在JavaScript中,不需要显式检查变量是否为null或未定义,因为:null或未定义在布尔表达式中返回false。
JS表达式从左到右。因此,对于
a || b
,如果a
为false,则仅评估b
。但是,如果a
为true,则不会检查b
。类似地,对于a && b
如果a
为false,则不会评估b
。因此,if (a != null) { "do something" }
可以写为if (a) { "do something" }
或简单地称为a && "do something"
。以相同的方式可以使用在值设置为null或未定义时设置默认值:
function someFunction(age){
:
var age= age|| 18;
:
}
someFunction(28)
结果为28,而someFunction()
结果为18。
评论
我个人的看法是?三元运算符仅在未嵌套时才值得使用。在您的情况下,这只会使代码更难以阅读和难以维护。我喜欢格式化嵌套的三元运算符,因此它们读起来就像是多个问题:codereview.stackexchange.com/a/6562/8891