I am working on an essentially very simple script that is supposed to do the following:

Loop over all Rectangles in a document

If certain criteria are met, make a copy of the current rectangle (on a different layer) and do some stuff with it

I can loop over the app.activeDocument.rectangles collection with no problem, but as soon as I duplicate an individual Rectangle object, the loop break. It seems that duplicating an element unshifts the copy onto the beginning of the array of objects represented by the Rectangles collection, rather than pushing it onto the end.

So if I have three Rectangle objects in the document (let’s make them red, green and blue, just to tell them apart), I’d initially get a collection like this:

Rectangles[0]: redBox

Rectangles[1]: greenBox

Rectangles[2]: blueBox

I loop over the collection and copy the current object on each iteration like so:

Doing this, I would (naïvely) expect the collection to end up looking like this:

Rectangles[0]: redBox

Rectangles[1]: greenBox

Rectangles[2]: blueBox

Rectangles[3]: redBox Copy

Rectangles[4]: greenBox Copy

Rectangles[5]: blueBox Copy

– but instead this is what happens:

Rectangles[0]: redBox Copy

Rectangles[1]: redBox Copy

Rectangles[2]: redBox Copy

Rectangles[3]: redBox

Rectangles[4]: greenBox

Rectangles[5]: blueBox

In other words, when I call orgEl.duplicate() in the first iteration (i = 0), the duplicated element is unshifted into the collection at position 0, and the current element’s index is moved up one, becoming 1. On the next iteration (i = 1), naturally, I get the same element again, since its position has moved since the start of the loop.

Now, it is of course possible to overcome the obstacle that this presents for looping over collections, by doing this for example:

But that’s rather unintuitive and cumbersome. I can think of several good reasons why duplicating an element onto the end of a collection would be usual and make sense, but I cannot think of a single good reason why adding it on to the beginning. All the effects I can think of are negative: the weirdness of modifying the index position of the current element, the rather significant performance hit that comes with unshifting compared to pushing, and just… general common sense.

So why is it that duplicate() apparently unshifts rather than pushing? Is there some logical reasoning behind this seemingly counterintuitive decision?

Oh, I see. So it’s not that the newly created elements are ‘unshifted’ onto the beginning of the collection, but rather that the entire collection gets recreated as soon as the element is created, and since the new element is in the same position as the old one, but on a higher layer (?), it ends up being the first in the new collection.