正如您将在下面看到的那样,我试图编写一些必须重复两次的逻辑 - 一次用于水平方向,另一次用于垂直方向。问题是每个方向都有不同的函数名称,并且它与其他可以通过整数迭代的场景不同。是否有更优雅的方式来重写它?
// Some calculations along the horizontal axis
someElementX.addEventListener('some-event', function(e){
var someResult = e.clientX - thisElement.style.left;
var someOtherResult = e.clientY; // Also some quick orthogonal calculation
});
// Some calculations along the vertical axis
someElementY.addEventListener('some-event', function(e){
var someResult = e.clientY - thisElement.style.top;
var someOtherResult = e.clientX; // Also some quick orthogonal calculation
});
这是我设法做到的一种方式,但是当代码重复被删除时,我觉得它令人难以置信的混乱,难以维护。
// Set up a "direction" loop
var loopParams =
{ 0: { xy: 'x', clientXY: { 1: 'clientX', 2: 'clientY' }, side: 'left' }
, 1: { xy: 'y', clientXY: { 1: 'clientY', 2: 'clientX' }, side: 'top' }
};
// Run the loop for each direction
for( var i = 0; i < 2; i++ )
{
var xy = loopParams[i].xy;
var clientXY = loopParams[i].clientXY;
var side = loopParams[i].side;
someElements[xy].addEventListener('some-event', function(e){
var someResult = e[clientXY[1]] - thisElement.style[side];
var someOtherResult = e[clientXY[2]]; // Some quick orthogonal calculation
});
}
有什么想法吗?
另外,我不确定该怎么称呼这个问题。有没有更好的术语来描述我在这里尝试做什么?
答案 0 :(得分:2)
总的来说,你的方法很好。但是,您的代码具有infamous Loop issue - 所有已安装的事件处理程序将使用上次迭代中的变量值。
您应该使用数组文字而不是对象文字,这样做的好处还在于您不需要loopParams
变量和显式for
- 循环当你可以使用forEach
- 免费获得关闭时。
[
{dir:'x', posProp:'clientX', otherProp:'clientY', side:'left'},
{dir:'y', posProp:'clientY', otherProp:'clientX', side:'top'}
].forEach(function(loopParam) {
someElements[loopParam.dir].addEventListener('some-event', function(e){
var someResult = e[loopParam.posProp] - thisElement.style[loopParam.side];
var someOtherResult = e[loopParam.otherProp]; // Some quick orthogonal calculation
});
});
当然你可以使用更多的succint变量&amp;财产名称。
您确实需要在增加复杂性的同时减轻重复使用的好处。对于只有两个相似的功能(如果它们真的像你的问题一样短),有这么多(4)个不同的部分,所获得的优势似乎不足以使这种重写成为必要。
这里可以应用的其他技术是:a)闭包工厂 - 不需要参数对象:
function addXYHandler(el, posProp, otherProp, side) {
el.addEventListener('some-event', function(e){
var someResult = e[posProp] - thisElement.style[side];
var someOtherResult = e[otherProp]; // Some quick orthogonal calculation
// much "duplicate" code
});
}
addXYHandler(someElementX, 'clientX', 'clientY', 'left');
addXYHandler(someElementY, 'clientY', 'clientX', 'top');
或b)仅使用不同的处理程序,并将外部函数中的常用功能外包出去:
function someResult(…) { … }
function someOtherResult(…) { … }
// or maybe use only one function with multiple parameters
var handlers = {
x: function(e) {
someResult(e.clientX - thisElement.style.left);
someOtherResult(e.clientY);
},
y: function(e){
someResult(e.clientY - thisElement.style.top);
someOtherResult(e.clientX);
}
});
for (var dir in handlers)
someElements[xy].addEventListener('some-event', handlers[dir]);