Javascript:在多个轴/方向上迭代/循环

Javascript: Iterate/loop through multiple axes/directions?

本文关键字:方向 迭代 循环 Javascript      更新时间:2023-09-26

正如您将在下面看到的,我试图编写一些必须重复两次的逻辑—一次用于水平方向,第二次用于垂直方向。问题是,每个方向都有不同的函数名,它不像其他场景,你可以通过整数迭代。有没有更优雅的方式来重写它?

// 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
  });
}

任何想法?

而且,我不确定该怎么称呼这个问题。有更好的术语来描述我在这里要做的吗?

总的来说,你的方法还不错。然而,你的代码有臭名昭著的循环问题-所有安装的事件处理程序将使用上次迭代的变量值。

你应该使用数组字面值而不是对象字面值,这也有一个好处,你不需要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
  });
});

当然你可以使用更简洁的变量&属性名。

您确实需要权衡消除重复的好处和增加的复杂性。对于只有两个相似的函数(如果它们真的像你的问题中那样短),有这么多(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]);