คำสั่ง for...in ออกแบบมาเพื่อ วนลูป Property Names (Keys) ของ Object ไม่ใช่สำหรับ Array แม้จะใช้ได้แต่ ไม่แนะนำ เพราะมีปัญหาหลายประการ
ตัวอย่างโค้ด (จากแหล่งที่มา)
<html>
<body>
<script>
var items = new Array('Hello', 'World');
var i = 0;
for (var i in items) {
document.write(items[i]);
}
</script>
</body>
</html>
❌ ปัญหาการใช้ for...in กับ Array
| ปัญหา | คำอธิบาย |
|---|---|
| Index เป็น String | "0", "1" แทน Number 0, 1 |
| ลำดับไม่รับประกัน | Spec ไม่กำหนดลำดับ (Browser ใหม่เรียงได้ แต่อาจแตกต่าง) |
| รวม Prototype Properties | ถ้ามี Array.prototype.custom = ... จะวนเข้ามาด้วย |
| รวม Custom Properties | arr.foo = 'bar' จะถูกวนด้วย |
| ช้ากว่า | ต้อง Lookup Property ทุกครั้ง |
| Sparse Array | ข้าม Empty Slots (Holes) ไป |
ตัวอย่างปัญหา
const arr = ['a', 'b', 'c'];
arr.customProp = 'test';
for (const key in arr) {
console.log(key, arr[key]);
}
// "0" "a"
// "1" "b"
// "2" "c"
// "customProp" "test" ← เข้ามาด้วย!
✅ ตัวเลือกที่ดีกว่าสำหรับ Array
1. for...of (ES2015) - แนะนำมากที่สุด
for (const value of ['a', 'b', 'c']) {
console.log(value); // 'a', 'b', 'c' (Value โดยตรง)
}
// ต้องการ Index
for (const [index, value] of ['a', 'b', 'c'].entries()) {
console.log(index, value); // 0 'a', 1 'b', 2 'c'
}
2. forEach (Functional)
['a', 'b', 'c'].forEach((value, index) => {
console.log(index, value);
});
3. Standard for Loop (เร็วที่สุด ต้องการ Control)
const arr = ['a', 'b', 'c'];
for (let i = 0, len = arr.length; i < len; i++) {
console.log(i, arr[i]);
}
4. Array Methods (Immutable/Declarative)
arr.map((v, i) => ...); arr.filter(v => ...); arr.reduce((acc, v) => ...); arr.find(v => ...); arr.some(v => ...);
เมื่อไหร่ควรใช้ for...in
- ✅ วน Properties ของ Plain Object:
for (const key in obj) - ✅ Debug/Inspect Object:
for (const k in obj) console.log(k, obj[k]) - ✅ กรองด้วย
hasOwnProperty:if (obj.hasOwnProperty(k)) - ❌ วน Array (ใช้ for...of)
- ❌ ต้องการ Index เป็น Number และลำดับแน่นอน
สรุป
for...in สำหรับ Object Keys | for...of สำหรับ Array/Iterable Values | for สำหรับ Index Control