优化轮游戏的Javascript循环

时间:2011-12-01 16:08:11

标签: javascript jquery loops

我正在创建一个游戏,其中灯光围绕圆圈运行,你必须尝试连续三次在同一地点停止灯光。目前,我正在使用以下代码循环灯光并将它们“打开”和“关闭”:

var num_lights = 20;
var loop_speed = 55;
var light_index = 0;
var prevent_stop = false; //If true, prevents user from stopping light

var loop = setTimeout(startLoop, loop_speed);

function startLoop() {
    prevent_stop = false;
    $(".light:eq(" + light_index + ")").css("background-color", "#fff");
    light_index++;
    if(light_index >= num_lights) {
        light_index = 0;
    }
    $(".light:eq(" + light_index + ")").css("background-color", "red");
    loop = setTimeout(startLoop, loop_speed);
}

function stopLoop() {
    clearTimeout(loop);
}

在大多数情况下,代码似乎运行得很好,但如果我在另一个标签中同时运行视频,那么灯的打开和关闭似乎有点突然。关于我如何可能加快速度的任何输入都会很棒。

有关上述代码的示例,请查看此页面:http://ericditmer.com/wheel

5 个答案:

答案 0 :(得分:2)

当优化要首先看的东西时,不要做两次你只需要做一次。从DOM中查找元素可能很昂贵,你肯定知道你想要哪些元素,那么为什么不预先获取所有元素并且多次无效呢?

我的意思是你应该

var lights = $('.light');

这样你以后可以说

 lights.eq(light_index).css("background-color", "red");

请确保在第二件事情中保留lights的范围。

编辑:每条评论更新。

答案 1 :(得分:2)

我会创建一个选择器引用的全局数组,因此每次调用函数时都不必执行它们的选择器。我还会考虑交换类名,而不是属性。

以下是jQuery性能的一些信息:

http://www.componenthouse.com/article-19

编辑:那篇文章虽然很老,但jQuery已经发展了很多。这是最近的:http://blog.dynatrace.com/2009/11/09/101-on-jquery-selector-performance/

答案 2 :(得分:1)

我要注意的一件事是你使用了setTimeout()并且真正设计它的行为就像setInterval()

请尝试使用setInterval()。我不是js引擎大师,但是我想认为setTimeout的不断重用必须对使用setInterval()(你只需要设置一次)所不具备的性能产生一些影响。

编辑:

Diodeus的Curtousy,一个支持我发言的相关帖子:

Related Stack Question - setTimeout() vs setInterval()

答案 3 :(得分:1)

您可以尝试将灯元素存储在数组中,而不是每次都使用选择器。类选择器可能有点慢。

var elements = $('.light');

function startLoop() {
    prevent_stop = false;
    $(elements[light_index]).css('background-color', '#fff');
    ...
}

这假设元素已经在DOM中按预期顺序排列。

答案 4 :(得分:0)

好的,这包括一些“最佳实践”改进,如果它真的优化了应该测试的执行速度。至少你可以宣称你现在正在编写忍者风格 lol

// create a helper function that lend the array reverse function to reverse the 
// order of a jquery sets. It's an object by default, not an array, so using it
// directly would fail
$.fn.reverse = Array.prototype.reverse;
var loop,
    loop_speed = 55,
    prevent_stop = false,
    // prefetch a jquery set of all lights and reverses it to keep the right
    // order when iterating backwards (small performance optimization)
    lights = $('.light').reverse();


// this named function executes as soon as it's initialized
// I wrapped everything into a second function, so the variable prevent_stop is
// only set once at the beginning of the loop
(function startLoop() {
    // keep variables always in the scope they are needed
    // changed the iteration to count down, because checking for 0 is faster.
    var num_lights = light_index = lights.length - 1;
    prevent_stop = false;
    // This is an auto-executing, self-referencing function
    // which avoids the 55ms delay when starting the loop
    loop = setInterval((function() {
        // work with css-class changing rather than css manipulation
        lights.eq( light_index ).removeClass('active');
        // if not 0 iterate else set to num_lights
        light_index = (light_index)? --light_index:num_lights;
        lights.eq( light_index ).addClass('active');
        // returns a referenze to this function so it can be executed by setInterval()
        return arguments.callee;
    })(), loop_speed);
})();


function stopLoop() {
    clearInterval(loop);
}

干杯neutronenstern