The for loop from earlier in this module works by manually managing an index — you create a counter, check it against a limit, and remember to update it every pass. Most of the time, when you're looping through an array, struct, list, or query, you don't actually care about the index itself — you just want each item.
CFScript's for...in loop (sometimes called a "foreach" loop in other languages) hands you each item directly, without a counter to manage. ColdFusion's <cfloop> tag has matching typed variants for each data structure.
Learning Objectives
After completing this lesson, you'll be able to:
- Loop over an array with for...in.
- Loop over a struct's keys with for...in.
- Loop over a list with for...in.
- Loop over query rows with for...in.
- Use the matching <cfloop> tag-syntax variant for each data type.
Looping Over an Array
No index counter to declare, check, or update — fruit is handed to you directly each pass.
Looping Over a Struct
For a struct, for...in gives you each key — use it to look up the matching value.
Struct keys come back in an unpredictable order in both CFScript and tag syntax — don't rely on the order matching how you defined them.
Looping Over a List
Looping Over Query Rows
for...in over a query hands you the current row as a struct-like object. query.currentRow gives you the row number if you need it.
Query loops are common enough to deserve their own deep dive — the next lesson (<cfloop>) covers additional options like grouping.
Real-World Example: Building an HTML List
Common Beginner Mistakes
Expecting struct key order to match insertion order
for (key in myStruct) doesn't guarantee keys come back in the order you added them — if order matters, loop over a sorted array of the keys instead (structKeyArray(myStruct) then sort it).
Trying to modify the array you're looping over
Adding or removing elements from an array while a for...in loop is iterating over it can produce unpredictable results. Build a new array instead, or loop by index with a plain for loop if you need to modify in place.
Forgetting query.currentRow starts at 1
Like arrays, query row numbers are 1-indexed, not 0-indexed — the first row is currentRow 1.
Best Practices
- Use for...in whenever you just need each item and don't care about its position.
- Fall back to a manual for loop when you specifically need the index — to compare neighboring items, for example.
- Name the loop variable after what it actually is (fruit, row, key) rather than a generic item.
Interview Questions
What does for...in give you when looping over an array?
Each element's value directly, without a manual index counter.
What does for...in give you when looping over a struct?
Each key — use user[key] to get the matching value.
What's the tag-syntax equivalent of for...in for an array?
<cfloop array="#arr#" index="item">.
What's the tag-syntax equivalent of for...in for a struct?
<cfloop collection="#myStruct#" item="key">.
Summary
In this lesson, you learned CFScript's for...in loop for arrays, structs, lists, and query rows, along with the matching <cfloop> tag-syntax variant for each. Reach for this style whenever you just need each item, and save manual index-based loops for when you specifically need the position.
What's Next?
The next lesson is a complete reference for <cfloop> — every loop type it supports in tag syntax, including options this module hasn't covered yet like file loops and query grouping.
Ready to Practice CFML?
Write and run real ColdFusion code online, on Adobe ColdFusion, no local install or signup required.
Practice CFML Online ↗Opens CFFiddle, a third-party CFML playground, in a new tab. External site terms and privacy policy apply.
Or try 50 CFML practice questions →