Brad sent me the following question today. (Hope he doesn't mind me posting it!)
I have a question for you that I hope you can help me with. I was wanting to create an array of objects by looping over a query. What I'm not sure about is if I should instantiate the object outside of the loop or if I should do it inside the loop. I'm not sure what would happen if I do it outside the loop...since I'd be inserting the same instance into the array, would all objects contain the value of the last loop iteration or would the array keep the correct object in it's index?
I knew the answer, but I wanted to double check, so I quickly wrote up the following example.
<cfset data = arrayNew(1)>
<cfloop index="x" from="1" to="10">
<cfset ob.name = "Name #x#">
<cfset data[x] = ob>
</cfloop>
<cfdump var="#data#">
The component, test, is an empty component, and any component would work in this example. Inside the loop, we set a value directly to the component. This is not something I normally do, but it makes for a good example. We then (or we think we do) copy the object to the array.
What happens when we dump it? We see an array of objects where all of the objects are named "Name 10".
This is an example of how components, and other complex objects in ColdFusion, are passed by reference, not by copy. To say that a bit simpler, when we do:
<cfset data[x] = ob>
We actually create a reference from data[x] to the original component object we created. All ten indexes of the array all point to the exact same component.
To answer the question, yes, you have to create a new instance of the object in the loop. In case you are curious, you can't use duplicate to fix the issue. If you use duplicate on a component in CFMX 7, you get an error. If you use it on CFMX 6 (or 6.1), something worse happens. You don't get an error, but the result of the duplicate operation is a structure, not a component.