Trong JS, typeof [] === 'object' — mảng là object đặc biệt. typeof không phân biệt được mảng và object thường.
typeof — Không đủ
<script>
const arr = [1,2,5,'hello'];
const obj = {};
document.write(typeof arr + '<br>'); // "object"
document.write(typeof obj + '<br>'); // "object" — không phân biệt được
</script>
Array.isArray() — Cách chuẩn
<script>
const arr = [1,2,5,'hello'];
const obj = {};
document.write(Array.isArray(arr) + '<br>'); // true
document.write(Array.isArray(obj) + '<br>'); // false
</script>
Tại sao Array.isArray() hoạt động?
Kiểm tra internal slot [[Array]] — đặc tính nội bộ của engine, không phụ thuộc prototype chain. Do đó:
- Đúng cross-realm (iframe, window).
- Đúng với subclass của Array.
- Không bị lừa bởi object giả mạo prototype.
Object.prototype.toString.call() — Cách cổ điển (ES3)
Object.prototype.toString.call(arr); // "[object Array]"
Object.prototype.toString.call(obj); // "[object Object]"
// Helper function
function isArrayOldSchool(val) {
return Object.prototype.toString.call(val) === '[object Array]';
}
So sánh 3 cách
| Phương pháp | Độ tin cậy | Cross-realm | Hiệu suất | Khuyến nghị |
|---|---|---|---|---|
| Array.isArray() | Cao nhất | Có | Nhanh | Mặc định |
| Object.prototype.toString.call() | Cao | Có | Trung bình | Legacy (IE8-) |
| instanceof Array | Trung bình | Không | Nhanh | Chỉ same realm |
| typeof | Thấp (không phân biệt) | N/A | Nhanh nhất | Không dùng cho mảng |
Array-like objects — Không phải mảng
const args = (function(){ return arguments; })();
const nodelist = document.querySelectorAll('div');
Array.isArray(args); // false
Array.isArray(nodelist); // false
// Chuyển thành mảng thật
const realArr1 = Array.from(args);
const realArr2 = [...nodelist];