简体   繁体   English

JavaScript循环问题

[英]Javascript For-Loop issue

I'm trying to click every item with a 200 millisecond interval, I wrote the following script however there seems to be an issue with the For Loop. 我试图以200毫秒的间隔单击每个项目,我编写了以下脚本,但是For循环似乎存在问题。 Some one please tell me what you think is wrong with it. 请有人告诉我您认为这有什么问题。

function clickLink(elm) {
    var evt = document.createEvent('MouseEvents');
    evt.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    elm.dispatchEvent(evt);
}

function sel() {
    elms = document.getElementsByClassName('uItem');
    var inputs= elms;
    var howbig= elms.length;
    console.log(howbig);

    for (var i=250;i<elms.length;i++)
    {
        setTimeout(clickLink(inputs[i]),200)
    };

There's 1400 uItem 's on the page. 页面上有1400个uItem。

Cleanest solution is just to have your clickLink function return a function. 最干净的解决方案就是让您的clickLink函数返回一个函数。

function clickLink(elm) {
    return function() {
        var evt = document.createEvent('MouseEvents');
        evt.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        elm.dispatchEvent(evt);
    };
}

Then stagger the timers if you want an interval: 然后,如果需要间隔,请错开计时器:

var start = 250
for (var i=start;i<elms.length;i++) {
    setTimeout(clickLink(elms[i]), 200 * (i - start))
}

Or ditch the loop, and use setInterval : 或者放弃循环,并使用setInterval

var i = 250,
    len = inputs.length;
var itvl = setInterval(function() {
    clickLink(elms[i++]);
    if (i >= len)
        clearInterval(itvl);
}, 200);

And to back to your original clickLink function 并返回到原始的clickLink函数

The easiest way, if you're using a moderately-recent version of JavaScript, is to use bind . 如果您使用的是中等版本的JavaScript,最简单的方法是使用bind This creates a single function object with arguments bound to it that are calculated when bind is called, not later. 这将创建一个具有绑定到其的参数的单个函数对象,该参数是在调用bind时计算的,而不是稍后进行计算。 The line you want is thus: 因此,您想要的行是:

setTimeout( clickLink.bind( null, inputs[i] ),  /* delay expression here */ )

You can make bound functions explicitly, but it's ugly and you should only do it if you have a strong requirement to support old JavaScript interpreters. 您可以显式地创建绑定函数,但这很丑陋,只有在您强烈要求支持旧的JavaScript解释器时才应该这样做。

There is a issue of the scope of ì , the delay which needs to be incremented accordingly with i to have a 200 ms interval and the fact that setTimeout expects a function as is argument. 存在ì范围的问题,该延迟需要随着i以200 ms的间隔相应地增加,并且setTimeout期望函数作为参数。

    for (var i=250;i<elms.length;i++)
    {
        setTimeout((function() {
            var j = i // keep i as j in this closure
            return function() { // return the right function
                clickLink(inputs[j])
            }
        })(),200 * i) // set the delay depending on i
    };
function sel() {
  var elems = document.getElementsByClassName('uItem');
  for (var i = 0; i < elems.length; i += 1) {
    setTimeout(function (el) {
      return function () {
        clickLink(el);
      };
    }(elems[i]), i * 1000);   
  };
}

demo: http://jsfiddle.net/4hYWy/ 演示: http : //jsfiddle.net/4hYWy/


little note : I don't like these constructs (calculating the delay like in the example). 小提示 :我不喜欢这些构造(像示例中那样计算延迟)。 But it is very close to the original code, and my solution of choice would have probably made it too complicated. 但这与原始代码非常接近,我选择的解决方案可能会使它过于复杂。

This code wait 200ms, execute a callback and prepare a new callback executed 200ms later. 此代码等待200毫秒,执行回调并准备在200毫秒后执行的新回调。 The second callback is executed 400ms after the call of sel and so on. 第二个回调是在sel调用之后400毫秒执行的,依此类推。

    var callback = function(i) {
        return function() {
            if (i < elms.length) {
                clickLink(inputs[i]);
                setTimeout(callback(i + 1), 200);
            }
        };
    };
    setTimeout(callback(250), 200);

The way your doing this won't get you one click per 200ms, you will register all your clicks almost at the same time(the time a loop last to iterate 1000 items,almost instantly) so you basically would get your 1000+ aprox. 这样一来,您不会每200毫秒获得一次点击,您几乎可以同时注册所有点击(一次循环几乎可以立即迭代1000个项目的时间),因此您基本上可以获得1000+个近似值。 click events fired almost simultaneously, I think that could cause issues, so to make sure they are executed once in a 200ms approx. 点击事件几乎同时触发,我认为这可能会引起问题,因此请确保它们在大约200毫秒内执行一次。 do this: 做这个:

window.i=250;
for (var i=250;i<elms.length;i++)
{
setTimeout(function() {
   clickLink(inputs[window.i]);
   window.i++;
},200 * (i-249)); //Here we make sure events are spaciated 200ms each approx.
};

UPDATE: Updated the anonymouse function to pass i to avoid closure issue noted in comments. 更新: 更新了匿名函数以传递 i以避免注释中指出的关闭问题。

UPDATE 2 : Added window.i inside anonymous function to workaround i scope issue 更新2 :在匿名函数中添加了window.i以解决i作用域问题

UPDATE 3 : Updated my code above to fix the interval at which each click event is fired, we were using 200 * i but that is only correct if i starts at zero, here it starts at 250 so the correct form is 200 * (i-249) 更新3 :更新了上面的代码,以固定每次单击事件触发的时间间隔,我们使用200 * i但这仅在i从零开始时正确,此处从250开始,因此正确的格式为200 * (i-249)

In spite of some comments, the i scope issue it's resolved using window.i , see test here https://tinker.io/98fd4/1 尽管有一些评论,但使用window.i解决了i范围问题,请参见此处进行测试https://tinker.io/98fd4/1

No scope issues or calculating correct interval. 没有范围问题或计算正确的间隔。

function sel() {
    var elms = document.getElementsByClassName('uItem'),
        i = -1,
        I = elms.length,

        rec = function () {
            if ( i++ < I ) {
                clickLinks(elms[i]);
                setTimeout(rec, 200);
            }
        };

    rec();
}

http://jsfiddle.net/joplomacedo/cqfxH/ http://jsfiddle.net/joplomacedo/cqfxH/

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

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