最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using shift() and push() to loop array values vs. using a counter variable, what is the best approach? - Stack Over

programmeradmin1浏览0评论

I'm looping through a set of images within an array of animation frames. There are 7 images, and looping from 1-7 pletes the animation. I need this animation to loop indefinitely, but I was wondering which of these is the best approach:

Loop by modifying array

/* Pull image from start of array. */
var image = frames.shift();
/* Process image. */
...
/* Add image back to end of array. */
frames.push(image );

Loop using counter variable

/* Pull image by counter offset. */
var image = frames[counter];
/* Process image. */
...
/* Increment or reset counter value. */
counter + 1 === frames.length ? counter = 0 : counter = counter + 1;

Is there a reason I'd chose one over the other? Alternatively, is there a better approach to this?

I'm looping through a set of images within an array of animation frames. There are 7 images, and looping from 1-7 pletes the animation. I need this animation to loop indefinitely, but I was wondering which of these is the best approach:

Loop by modifying array

/* Pull image from start of array. */
var image = frames.shift();
/* Process image. */
...
/* Add image back to end of array. */
frames.push(image );

Loop using counter variable

/* Pull image by counter offset. */
var image = frames[counter];
/* Process image. */
...
/* Increment or reset counter value. */
counter + 1 === frames.length ? counter = 0 : counter = counter + 1;

Is there a reason I'd chose one over the other? Alternatively, is there a better approach to this?

Share Improve this question asked Apr 6, 2013 at 21:42 James DonnellyJames Donnelly 129k35 gold badges214 silver badges223 bronze badges 4
  • 4 I'd use counter % frames.length. Array operations are rather heavy and shift causes the array items' indexes to be re-enumerated, while a property lookup is quite cheap. – Fabrício Matté Commented Apr 6, 2013 at 21:45
  • FWIW, you can loop around with the counter using the modulus operator: counter = (counter + 1) % frames.length; edit: What Fabrício said ;) – Felix Kling Commented Apr 6, 2013 at 21:45
  • Ah I hadn't considered modulus at all. How simple! – James Donnelly Commented Apr 6, 2013 at 21:53
  • If you felt like being fancy, you could loop over them once and say image.next = frames[(i + 1) % frames.length];. Then in your animation just hold on to the last image you processed, and say something like image = image.next; and never bother with arrays or counters again... :) – cHao Commented Apr 6, 2013 at 21:57
Add a ment  | 

3 Answers 3

Reset to default 5

Modifying the array is going to be more expensive than simply using a variable to keep track of your position in the array. The better way to do this, if you're looping indefinitely, seems to just be to use a while loop (rather than using a for loop where you reset the counter inside):

var i = 0;
while (true) {
    doSomething to array[i];

    i = (i+1) % array.length;
}

However if your goal really is having an animation proceed indefinitely every time a given interval elapses, a loop isn't ideal at all. Use setInterval instead.

var frames = ...; //your images
var i = 0;
function animate() {
    do something to frames[i];
    i = (i+1) % array.length;
}

setInterval(animate, time_between_runs);

where time_between_runs is how much time should elapse before the function is called again.

Alternatively a circular linked list also can be used I think. To turn an array of objects into a circular linked list:

frames.forEach(function(elem, index) { 
    elem.next = frames[index + 1] || frames[0];
});

And now you can do something like this:

setInterval(function() {
    frame = frame.next;
    ....
}, delay);

One possibility is to ditch the array and use a linked list.

Make each frame an object that points to the next object. The last one then points to the first. Then all you need to do is reference the next object.

var curr = first; // reference to first frame object

setInterval(function() {

    // process image
    curr.image.doSomething();

    // proceed to next
    curr = curr.next;

}, 1000);

No counters to mess with this way.


Setting up the linked list is usually pretty simple, and can likely be done with just a little modification to the current code that's setting up the Array.

var first = new Frame(); // This is your entry point
var current = first;        // This holds the current frame during setup

for (var i = 0; i < totalFrames; i++) {
    current.next = new Frame();   // Make the current reference a new frame
    current = current.next;          // Make the new frame current
}

current.next = first; // circular reference back to the first.

function Frame() {
    // set up this frame
}

Then first is your starting point.


Or the linking could be done within the Frame constructor.

var first = new Frame(null); 
var current = first;

for (var i = 0; i < totalFrames; i++) {
    current = new Frame(current);
}

current.next = first;

function Frame(currFrame) {
    // link this frame to the given one
    if (currFrame)
        currFrame.next = this;

    // set up the rest of this frame
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论