优化车轮游戏的Javascript循环

Optimizing Javascript Loop for Wheel Game

本文关键字:Javascript 循环 游戏 优化      更新时间:2023-09-26

我正在创造一款游戏,其中灯光会围绕着一个圆圈的外部运行,你必须尝试着连续三次将灯光停在同一地点。目前,我正在使用以下代码循环遍历灯并将它们"打开"answers"关闭":

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

当优化的东西看第一不是做两次,你只需要做一次。从DOM中查找元素可能会很昂贵,而且你肯定知道你想要哪些元素,所以为什么不预先取到所有元素,然后重复多次呢?

我的意思是你应该

var lights = $('.light');

之后你可以直接写

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

只是要确保在一个地方做第一件事,使lights在第二件事的范围内。

编辑:每条评论更新

我会让你的选择器引用的全局数组,所以他们的选择器不必执行每次函数调用。我还会考虑交换类名,而不是属性。

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

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

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

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

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

这里假设元素在DOM中已经按照它们的顺序排列。

我要注意的一件事是,您使用了setTimeout(),并且实际上只是将其设计为像setInterval()一样。

尝试使用setInterval()代替。我不是js引擎大师,但我想认为setTimeout的不断重用必须对性能有一些影响,不会出现使用setInterval()(你只需要设置一次)。

编辑:

dideus的curcury,一个相关的帖子来支持我的说法:

相关堆栈问题- setTimeout() vs setInterval()

好的,这包括了一些"最佳实践"的改进,如果它真的优化了执行速度应该进行测试。至少你可以宣称你现在正在编写忍者风格的代码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