我有两个非常相似的功能。我想过使用字符串和eval('Man')
,但如果可能的话,我很乐意避免使用它。如何抽象这两个,所以它只有一个功能?
function showMan() {
widget.classList.add(toggle);
fx.wipeOut({
node: calWoman
}).play();
fx.wipeOut({
node: pointsWoman
}).play();
pointsMan.classList.remove(toggle);
fx.wipeIn({
node: calMan
}).play();
fx.wipeIn({
node: pointsMan
}).play();
mtFields();
inputMan.focus();
}
function showWoman() {
widget.classList.add(toggle);
fx.wipeOut({
node: calMan
}).play();
fx.wipeOut({
node: pointsMan
}).play();
pointsWoman.classList.remove(toggle);
fx.wipeIn({
node: calWoman
}).play();
fx.wipeIn({
node: pointsWoman
}).play();
mtFields();
inputWoman.focus();
}
/** @todo abstract and create one function - showPerson('Man') */
答案 0 :(得分:4)
如果将所有变量合并到一个对象中会更容易。
function showPerson(sex) {
var people = {
woman: {
cal: calWoman,
points: pointsWoman,
input: inputWoman
},
man: {
cal: calMan,
points: pointsMan,
input: inputMan
}
};
sex = sex.toLowerCase();
var otherSex = sex === 'man' ? 'woman' : 'man';
var show = people[sex];
var hide = people[otherSex]
widget.classList.add(toggle);
fx.wipeOut({
node: hide.cal
}).play();
fx.wipeOut({
node: hide.points
}).play();
show.points.classList.remove(toggle);
fx.wipeIn({
node: show.cal
}).play();
fx.wipeIn({
node: show.points
}).play();
mtFields();
show.input.focus();
}
// usage
showPerson('man');
showPerson('woman');
答案 1 :(得分:1)
创建一个函数showPerson
,该函数接受gender
作为参数。
从那里,你可以创建一个对象,在其中封装性别特定的函数,然后引用它的对立面:
function showPerson(gender) {
var optionsObj = {
man: {
cal: calMan,
points: pointsMan,
input: inputMan.focus,
},
woman: {
cal: calWoman,
points: pointsWoman,
input: inputWoman.focus,
}
}
gender === 'man' ? optionsObj[gender].opposite = optionsObj.woman : optionsObj[gender].opposite = optionsObj.man;
widget.classList.add(toggle)
fx.wipeOut({
node: optionsObj[gender].cal,
}).play();
fx.wipeOut({
node: optionsObj[gender].points
}).play();
optionsObj[gender].points.classList.remove(toggle);
fx.wipeIn({
node: optionsObj[gender].opposite.cal
}).play();
fx.wipeIn({
node: optionsObj[gender].opposite.points
}).play();
mtFields();
optionsObj[gender].input()
}
答案 2 :(得分:1)
考虑到这里所有内容的顺序,这有点令人困惑,但诀窍不是将两个巨大的功能分解为一个,而是将系统分解成可以更好地组合的较小部分。
function hideNode ( node ) { fx.wipeOut({ node: node }).play(); }
function revealNode ( node ) { fx.wipeIn({ node: node }).play(); }
function showPerson (removalList, revealList, points, input) {
widget.classList.add(toggle);
removalList.forEach(hideNode);
points.classList.remove(toggle);
revealList.forEach(revealNode);
input.focus();
}
// somewhere NORTH of your current function
var womanList = [calWoman, pointsWoman];
var manList = [calMan, pointsMan];
var revealList, removalList, input, points;
if (man) {
removalList = womanList;
revealList = manList;
input = inputMan;
points = pointsMan;
} else {
removalList = manList;
revealList = womanList;
input = inputWoman;
points = pointsWoman;
}
// alternatively, these can be stored in an object this way, and pulled by a flag, rather than by an if statement...
showPerson( removalList, revealList, points, input );
如果你注意到,逻辑依旧非常简单,依赖于将参数传递给我的函数 选择值的逻辑也很简单,但我已经不再需要在函数之外选择;这是其他人的关注(即使它是一个新功能,除了选择并传递适当的值之外什么都不做)。
我已经在函数中执行了重复步骤,并将它们分解为更小的函数,并且我正在使用列表(甚至只是两个列表),因此我可以忽略调用某些内容的详细信息......它和你发给我的人完全一样被打电话
我还没有解决“谁叫showPerson,有什么和什么访问......”,但这是一个更具体的问题需要解决;从这里开始包装任何使用if () { }
和值设置/传递的人都很快。
这远不是一个干净的成品,但它提供的提供的是如何在更大的项目中处理这些移动部件。
为了更进一步,并且为了表明你不需要在重写方面做太多,这里(至少不是最初的),我将进一步增加:
function getPersonConfig ( type ) {
var config = {
man: { /* ... */ },
woman: { /* ... */ }
};
return config[type];
}
function showMan () {
var config = getPersonConfig( "man" );
showPerson( config );
}
function showWoman () {
var config = getPersonConfig( "woman" );
showPerson( config );
}
我正在使用 稍微 不同版本的showPerson
功能...
在其中,我传递了一个对象(而不是单独的变量),但这就是我需要改变的所有内容。
看看这些小巧,可组合的功能给我带来了什么......
您根本不必更改showMan
或showWoman
相反,你正在劫持他们曾经的东西,并使用它们来调用执行相同工作的较小函数,但现在更加可分离和可重用。
这是一个“外观”或“贴面”,通常在工程中,它是一个被讨论的API或服务,但它基本上意味着当你想要更新代码时,如果你可以保留方法名称,输入和输出以及所有后果相同(来自外部世界可以告诉),然后您可以根据需要更改代码的内部结构。
showMan
仍然被调用,现在它正在做的事情仍在进行中,没有任何添加或删除。
与showWoman
相同。
所以你已经成功地保留了一个立面,同时取代了内部。
外墙也可以走另一条路;以您希望它向外界展示的方式编写新的服务/ API,并将其发布到世界上,只需将旧代码挂钩到新结构,然后随时填写新功能
希望这有帮助。
答案 3 :(得分:0)
function showPerson(calPerson, pointsPerson, inputPerson) {
//replace calWoman and calMan with calPerson
//replace pointsMan and pointsWoman with pointsPerson
//replace inputMan and inputWoman with inputPerson
}
如果你无法传递它,可以使用闭包来初始化带有这些引用的函数。
function showPerson(calPerson, pointsPerson, inputPerson) {
function showingPersonWithReferences() {
//replace calWoman and calMan with calPerson
//replace pointsMan and pointsWoman with pointsPerson
//replace inputMan and inputWoman with inputPerson
}
return showingPersonWithReferences;
}
这是javascript中的一些函数式编程。
答案 4 :(得分:0)
尽管上面提供了出色的解决方案和建议,但我最终还是做了这个,这对我的情况最有效(最少改写,大多数干预)。非常感谢您回答这个问题。
function showPerson() {
/**
* the element being hidden should be placed in the first parameter
* @param {object} woman - HTMLFormElement (pointsWoman)
* @param {object} man - HTMLFormElement (pointsMan)
* @example showPerson(pointsWoman, pointsMan);
*/
if (arguments[0] instanceof HTMLFormElement && arguments[1] instanceof HTMLFormElement) {
widget.classList.add(toggle);
fx.wipeOut({
node: arguments[0]
}).play();
arguments[1].classList.remove(toggle);
fx.wipeIn({
node: arguments[1]
}).play();
mtFields();
arguments[1][0].focus();
}
else {
throw new Error('You need to provide the forms to show/hide');
}
}