Kiểm tra kiểu của các đối tượng trong JS được thực hiện thông qua instanceof
, tức là
obj instanceof Array
Điều này sẽ không hoạt động nếu đối tượng được vượt qua các ranh giới khung vì mỗi khung có Array
đối tượng riêng . Bạn có thể giải quyết vấn đề này bằng cách kiểm tra thuộc tính [[Class]] nội bộ của đối tượng. Để có được nó, hãy sử dụng Object.prototype.toString()
(điều này được đảm bảo hoạt động bởi ECMA-262):
Object.prototype.toString.call(obj) === '[object Array]'
Cả hai phương thức sẽ chỉ hoạt động cho các mảng thực tế chứ không phải các đối tượng dạng mảng như arguments
danh sách đối tượng hoặc nút. Vì tất cả các đối tượng giống mảng phải có thuộc tính số length
, tôi sẽ kiểm tra những điều này như sau:
typeof obj !== 'undefined' && obj !== null && typeof obj.length === 'number'
Xin lưu ý rằng các chuỗi sẽ vượt qua kiểm tra này, điều này có thể dẫn đến sự cố vì IE không cho phép truy cập vào các ký tự của chuỗi theo chỉ mục. Do đó, bạn có thể muốn thay đổi typeof obj !== 'undefined'
thành typeof obj === 'object'
để loại trừ các đối tượng gốc và đối tượng lưu trữ có các loại khác biệt với tất cả 'object'
. Điều này sẽ vẫn cho phép các đối tượng chuỗi đi qua, điều này sẽ phải được loại trừ theo cách thủ công.
Trong hầu hết các trường hợp, điều bạn thực sự muốn biết là liệu bạn có thể lặp lại đối tượng thông qua các chỉ mục số hay không. Do đó, bạn nên kiểm tra xem đối tượng có thuộc tính được đặt tên 0
thay thế hay không, có thể được thực hiện thông qua một trong các kiểm tra sau:
typeof obj[0] !== 'undefined' // false negative for `obj[0] = undefined`
obj.hasOwnProperty('0') // exclude array-likes with inherited entries
'0' in Object(obj) // include array-likes with inherited entries
Việc ép kiểu thành đối tượng là cần thiết để hoạt động chính xác đối với các nguyên mẫu giống như mảng (tức là chuỗi).
Đây là mã để kiểm tra mạnh mẽ các mảng JS:
function isArray(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
và các đối tượng giống mảng có thể lặp lại (tức là không rỗng):
function isNonEmptyArrayLike(obj) {
try { // don't bother with `typeof` - just access `length` and `catch`
return obj.length > 0 && '0' in Object(obj);
}
catch(e) {
return false;
}
}