我继承了一个用于浏览和配置产品的大型 JavaScript (MooTools) 应用程序。
其中有一个跟踪产品配置状态的函数。根据产品所处的状态调用其他函数。
我扩展它以添加一些新功能,但最终在一个大 switch 语句中出现了一堆嵌套条件。
我的问题是,您如何重构条件逻辑?是否有用于跟踪状态的通用(或 JS 特定)模式/技术?
更新:这里有一个伪版本的函数来说明问题:
switchToVariation: function(link) {
// set the variables
// before switch, set state
switch ( nextType ) {
case 'type1':
if ( prevType == 'type1' ) {
if ( nextIsSameVariation ) {
// do stuff
} else {
if ( nextIsSomethingElse ) {
// do stuff
}
// more stuff
}
} else {
// different stuff
}
break;
case 'type2':
if ( prevWasType1 ) {
// stuff
} else {
if (nextIsSameStyle) {
// stuff
}
// more stuff
}
break;
default:
// default stuff
}
// after switch, set state
}
最佳答案
当然,主要的答案是:将其分解成更小的部分,每个部分都做好一件事。
如果没有看到示例很难说得更具体,但是您说过“...在一个大的 switch 语句中有一堆条件...”这无疑提供了改进的机会:您可以移动每个案例都有自己的功能。
如果这样做,您有两个选择:要么使函数仅使用您传递给它们的参数工作,这往往会使事情更加模块化,要么使在外部函数中操作数据的函数闭包。我想说后者不太理想——对于这些目的——但这样做可能更快,因此是一个“速赢”。
假设我们最初有:
function myBigFunction() {
var v1, v2, v3;
/* ...set v1, v2, and v3 to various things...*/
switch (condition) {
case foo:
/* ...do lots of stuff involving v1 and v2...*/
break;
case bar:
/* ...do lots of stuff involving v1 only...*/
break;
case charlie:
/* ...do lots of stuff involving v2 and v3...*/
break;
}
}
然后:
第一种选择:完全独立的功能:
function myBigFunction() {
var v1, v2, v3;
/* ...set v1, v2, and v3 to various things...*/
switch (condition) {
case foo:
doFooStuff(v1, v2);
break;
case bar:
doBarStuff(v1);
break;
case charlie:
doCharlieStuff(v2, v3);
break;
}
}
function doFooStuff(v1, v2) {
}
function doBarStuff(v1) {
}
function doCharlieStuff(v2, v3) {
}
...当然,您可能需要让这些函数返回一些内容然后进行处理,例如:
case foo:
v1 = doFooStuff(v1, v2);
break;
...如果 doFooStuff
需要更新 v1
。如果它需要更新 v1
和 v2
,你可以返回一个数组,或者创建 v1
和 v2
属性您传递给 doFooStuff
等的对象。这是使用属性的示例:将 v1
和 v2
属性替换为对象 ( vdata
) 上有 v1
和 v2
properties:
var vdata = {
v1: "someInitialValue",
v2: "someInitialValue"
};
...然后调用 doFooStuff
:
case foo:
doFooStuff(vdata);
break;
...这允许 doFooStuff
更新 v1
和 v2
。但要小心,您不想创建一个包含所有 myBigFunction
变量的厨房水槽,那样会牺牲模块化。
第二种选择:使用闭包并直接使用父函数的数据:
function myBigFunction() {
var v1, v2, v3;
/* ...set v1, v2, and v3 to various things...*/
switch (condition) {
case foo:
doFooStuff();
break;
case bar:
doBarStuff();
break;
case charlie:
doCharlieStuff();
break;
}
function doFooStuff() {
// work with v1 and v2 directly
}
function doBarStuff() {
// work with v1 directly
}
function doCharlieStuff() {
// work with v2 and v3 directly
}
}
请注意,这里的各种子例程都是 myBigFunction
中的闭包,因此它们可以直接访问所有 myBigFunction
的局部变量。这是更加模块化的,但不完全是第一个选项的完整模块化方法。这也像是局部版本的函数处理全局变量的问题:副作用很容易引入并且会引起麻烦。
首选第一个选项,但如果不切实际,第二个选项至少可以帮助您使主线逻辑更清晰。当然,两者结合也可能有效。
关于javascript - 如何重构javascript中的条件逻辑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3767659/