简体   繁体   English

Javascript:遍历/遍历多个轴/方向?

[英]Javascript: Iterate/loop through multiple axes/directions?

As you'll see below, I'm trying to write some logic that has to be repeated twice - once for the horizontal direction, and a second time for the vertical direction. 正如您将在下面看到的那样,我正在尝试编写一些必须重复两次的逻辑-一次用于水平方向,第二次用于垂直方向。 The problem is that each direction has different function names and it's not like other scenarios where you can iterate via integers. 问题在于每个方向都有不同的函数名称,并且与其他可以通过整数进行迭代的方案不同。 Is there a more elegant way to rewrite it? 有没有更优雅的重写方式?

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

Here's a way I've managed to do it, but while the code duplication is eliminated, I feel like it's incredibly confusing and hardly maintainable. 这是我设法做到的一种方法,但是在消除了代码重复的同时,我感到它令人难以置信,而且难以维护。

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

Any ideas? 有任何想法吗?

Also, I wasn't sure what to call the question. 另外,我不确定该怎么称呼这个问题。 Is there a better terminology to describe what I'm trying to do here? 有没有更好的术语来描述我要在这里做什么?

In general, your approach was fine. 通常,您的方法很好。 However your code has the infamous Loop issue - all installed event handlers will use the variable values from the last iteration. 但是,您的代码存在臭名昭著的Loop问题 -所有已安装的事件处理程序都将使用上次迭代中的变量值。

You should use an array literal instead of an object literal, which also has the advantage that you don't need the loopParams variable and the explicit for -loop when you can just use forEach - getting the closure for free. 您应该使用数组文字而不是对象文字,这还具有以下优点:只要可以使用forEach ,就不需要loopParams变量和显式的for loopParams免费获取闭包。

[
  {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
  });
});

Of course you may use more succint variable & property names. 当然,您可以使用更多简洁的变量和属性名称。

You do need to weight the benefits of eleminating duplication against the added complexity. 您确实需要权衡消除重复的好处和增加的复杂性。 For only two similar functions (if they're really as short as in your question) with so many (4) different pieces the advantage gained does not seem large enough to make this rewrite necessary. 对于只有两个相似的函数(如果它们确实确实短于您的问题),却有这么多(4)个不同的部分,所获得的优势似乎还不足以使这种重写成为必要。


Other techniques that could be applied here are a) the closure factory - removing the need for a parameter object: 其他可以在此处应用的技术是: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');

or b) just using different handlers, and outsourcing the common functionality in external functions: 或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]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM