Câu hỏi Làm thế nào để bạn kiểm tra xem một biến là một mảng trong JavaScript? [bản sao]


Câu hỏi này đã có câu trả lời ở đây:

Tôi muốn kiểm tra xem một biến là một mảng hoặc một giá trị duy nhất trong JavaScript.

Tôi đã tìm thấy một giải pháp có thể ...

if (variable.constructor == Array)...

Đây có phải là cách tốt nhất có thể thực hiện được không?


1481
2018-04-20 09:02


gốc


Việc kiểm tra một đối tượng là một mảng có một số cảnh báo cụ thể ... Câu trả lời của Peter là câu trả lời duy nhất bạn nên sử dụng. - aleemb
@Andy Có vẻ như câu trả lời của tôi không phải là tốt nhất. Có lẽ bạn nên chọn một câu trả lời khác như được chấp nhận? - Peter Smit
Good điểm Peter. Tôi đã không nhận ra câu trả lời của bạn đã nhận được ý kiến ​​như thế này. Tôi nghĩ rằng từ lâu tôi đã bắt đầu sử dụng hàm JQuery.isArray khi kiểm tra mảng, và điều thú vị là được thực hiện khác với bất kỳ câu trả lời nào khác được đưa ra ở đây. Tôi đã đánh dấu câu trả lời phổ biến là chính xác. - Andy McCluggage
Xin lỗi đó là sai. Tôi nhìn một chút sâu hơn và (như của phiên bản 1.6.2) JQuery vẫn gõ kiểm tra bằng cách sử dụng so sánh trong các hình thức .... toString.call (obj) === "[object Array]" - Andy McCluggage
Đối với hỗ trợ IE8 tôi sẽ làm điều này if ('push' in variable.__proto__), cách nhanh nhất và có thể là tốt nhất để kiểm tra xem một số var có phải là mảng hay không. - thednp


Các câu trả lời:


Có nhiều cách để kiểm tra xem một biến có phải là một mảng hay không. Giải pháp tốt nhất là giải pháp bạn đã chọn.

variable.constructor === Array

Đây là phương pháp nhanh nhất trên Chrome và rất có thể là tất cả các trình duyệt khác. Tất cả các mảng là các đối tượng, do đó việc kiểm tra thuộc tính của hàm tạo là một quá trình nhanh cho các công cụ JavaScript.

Nếu bạn gặp vấn đề với việc tìm ra nếu một thuộc tính đối tượng là một mảng, trước tiên bạn phải kiểm tra xem thuộc tính có ở đó hay không.

variable.prop && variable.prop.constructor === Array

Một số cách khác là:

variable instanceof Array

Phương pháp này chạy về 1/3 tốc độ làm ví dụ đầu tiên. Vẫn còn khá vững chắc, trông sạch hơn, nếu bạn là tất cả về mã đẹp và không quá nhiều về hiệu suất. Lưu ý rằng việc kiểm tra các số không hoạt động như variable instanceof Number luôn luôn trả về false. Cập nhật: instanceof bây giờ đi 2/3 tốc độ!

Array.isArray(variable)

Điều cuối cùng này, theo ý kiến ​​của tôi là xấu nhất, và nó là một trong những chậm nhất. Chạy khoảng 1/5 tốc độ làm ví dụ đầu tiên. Array.prototype, thực sự là một mảng. Bạn có thể đọc thêm về nó ở đây https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

Vì vậy, một bản cập nhật khác

Object.prototype.toString.call(variable) === '[object Array]';

Anh chàng này là người chậm nhất để cố gắng kiểm tra một Array. Tuy nhiên, đây là cửa hàng một cửa cho bất kỳ loại nào bạn đang tìm kiếm. Tuy nhiên, vì bạn đang tìm kiếm một mảng, chỉ cần sử dụng phương pháp nhanh nhất ở trên.

Ngoài ra, tôi chạy một số thử nghiệm: http://jsperf.com/instanceof-array-vs-array-isarray/33 Vì vậy, có một số thú vị và kiểm tra xem nó ra.

Lưu ý: @EscapeNetscape đã tạo một thử nghiệm khác khi jsperf.com bị hỏng. http://jsben.ch/#/QgYAV Tôi muốn chắc chắn rằng liên kết ban đầu ở lại bất cứ khi nào jsperf trở lại trực tuyến.


1319
2017-10-29 15:07



Để mở rộng câu trả lời đã cho kiểm tra jsperf tại đây bằng cách sử dụng tính năng kiểm tra (.push && .pop) là cách tha nhanh nhất và được hỗ trợ trong tất cả các trình duyệt (thậm chí cả các trình duyệt cũ). Bắt là có lẽ một đối tượng có 'đẩy' và 'pop' tài sản mà không bị một mảng. Cũng lưu ý rằng khi thử nghiệm nếu là mảng với một đối tượng được tạo ra (hoặc được truyền) từ một khung khác, hầu hết các thử nghiệm sẽ thất bại (vì Mảng trong cửa sổ cho trước khác với Mảng trong khung cửa sổ). Ngoài ra có một bắt nếu một mảng được xây dựng thông qua mảng mới hoặc literaly như [..] - Nikos M.
Lưu ý rằng nếu bạn không chắc chắn nếu biến được xác định hoặc nếu biến đó có thể là null, hãy đảm bảo thực hiện các kiểm tra đó trước tiên vì đó là các giá trị / đối tượng chung không có hàm tạo. - Michael Scott Cuthbert
variable.constructor chỉ nhanh hơn để kiểm tra các mảng thực tế. Khi kiểm tra các đối tượng ngẫu nhiên (và trong thế giới thực, đây sẽ là trường hợp vì đây là lý do tại sao bạn sử dụng hàm này) nó nhanh hơn để sử dụng instanceof. jsperf.com/check-if-variable-is-array - Dinu Sorin
Chú ý: 'variable.constructor === Array' sẽ ném EXCEPTION nếu biến là null nhưng 'instance instanceof Array' thì không! - JerryGoyal
Tính năng của Chrome 59 isArray () có vẻ nhanh hơn đáng kể, nên tôi thấy không có lý do gì để không sử dụng isArray () trong mọi tình huống. - Hedley Smith


Bạn cũng có thể sử dụng:

if (value instanceof Array) {
  alert('value is Array!');
} else {
  alert('Not an array');
}

Điều này dường như với tôi một giải pháp khá thanh lịch, nhưng với mỗi của riêng mình.

Chỉnh sửa:

Tính đến ES5, bây giờ cũng có:

Array.isArray(value);

Nhưng điều này sẽ phá vỡ trên các trình duyệt cũ hơn, trừ khi bạn đang sử dụng polyfills (về cơ bản ... IE8 hoặc tương tự).


982
2018-04-20 09:05



Tôi đề nghị, thực sự nhấn mạnh vào gắn bó với điều này "instanceof" nhà điều hành nếu bạn không làm việc với nhiều khung hình. Đây là cách kiểm tra đúng loại đối tượng. - BYK
Một trong những trường hợp này sẽ thất bại là nếu bạn đang cố gắng để kiểm tra cho một mảng hoặc đối tượng kể từ Array instanceof Object == true. - Pierre
Nếu bạn đang sử dụng jQuery để vượt qua các phần tử với tìm ('code') hoặc một cái gì đó tương tự bạn sẽ muốn kiểm tra biến với variable instanceof Object vì nó không phải là một thể hiện của một mảng. - tuck
@BrettBender Nếu bạn vẫn còn hoạt động, bạn có thể cập nhật câu trả lời của bạn để phản ánh rằng như của ES5 chúng tôi có Array.isArray? - AndrewK
@AndrewK xem Câu trả lời của Fela Winkelmolen, có phương pháp Array.isArray. Đối với câu trả lời này, nó có thể không phải là một ý tưởng tuyệt vời để morph một câu trả lời vào một câu trả lời khác nhau thông qua chỉnh sửa. - muffin


Tôi nhận thấy ai đó đã đề cập đến jQuery, nhưng tôi không biết có một isArray() chức năng. Hóa ra nó đã được thêm vào trong phiên bản 1.3.

jQuery thực hiện nó như Peter gợi ý:

isArray: function( obj ) {
    return toString.call(obj) === "[object Array]";
},

Tôi đã nâng cấp lên phiên bản 1.3 và sử dụng chức năng của họ (với điều kiện nâng cấp không gây ra quá nhiều vấn đề) hoặc sử dụng phương pháp được đề xuất này trực tiếp trong mã.

Rất cám ơn vì những gợi ý.


72
2018-04-20 10:10



Xem bài viết này để có một cuộc thảo luận tốt về chủ đề này. Kết luận là sử dụng giải pháp này. - Nick G.
Điều này mang lại cho tôi lỗi SCRIPT65535 trong IE10. - polm23


Có nhiều giải pháp với tất cả những điều kỳ quặc của riêng họ. Trang này đưa ra một cái nhìn tổng quan tốt. Một giải pháp có thể là:

function isArray(o) {
  return Object.prototype.toString.call(o) === '[object Array]'; 
}

71
2018-04-20 09:08



Nếu bạn đọc cẩn thận, nó nói rằng phương pháp này là cần thiết khi bạn đang làm việc với các tài liệu nhiều khung mà, không được khuyến cáo. Phương pháp này có thể dễ dàng borke trên một chút thay đổi trong "toString" chức năng. - BYK
Do đó, liên kết được đưa ra để Brett có thể kiểm tra chúng và xem trong trường hợp nào chức năng của anh ta phải hoạt động - Peter Smit
@icCube Xin vui lòng, cho biết lý do tại sao nó không phải là con đường để đi! - Peter Smit
Xem câu trả lời của tôi dưới đây. Tôi đề nghị Peter Smit. - Brian
Phương pháp này là được đề xuất bởi Mozilla. - Hank


Trong các trình duyệt hiện đại (và một số trình duyệt cũ), bạn có thể làm

Array.isArray(obj)

(Được hỗ trợ bởi Chrome 5, Firefox 4.0, IE 9, Opera 10.5 và Safari 5)

Nếu bạn cần hỗ trợ các phiên bản cũ hơn của IE, bạn có thể sử dụng es5-shim để polyfill Array.isArray; hoặc thêm các mục sau

# only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
  Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  }
};

Nếu bạn sử dụng jQuery, bạn có thể sử dụng jQuery.isArray(obj) hoặc là $.isArray(obj). Nếu bạn sử dụng dấu gạch dưới, bạn có thể sử dụng _.isArray(obj)

Nếu bạn không cần phát hiện các mảng được tạo trong các khung khác nhau, bạn cũng có thể sử dụng instanceof

obj instanceof Array

chú thích: các arguments từ khóa có thể được sử dụng để truy cập đối số của một hàm không phải là một mảng, mặc dù nó (thường) hoạt động giống như một:

var func = function() {
  console.log(arguments)        // [1, 2, 3]
  console.log(arguments.length) // 3
  console.log(Array.isArray(arguments)) // false !!!
  console.log(arguments.slice)  // undefined (Array.prototype methods not available)
  console.log([3,4,5].slice)    // function slice() { [native code] } 
}
func(1, 2, 3)

54
2018-01-08 07:37



Đây có lẽ là cách tiếp cận hiện đại nhất. Tôi đã nhìn thấy nó cùng với các polyfill trên MDN để có nghĩa là Mozilla tin tưởng nó developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - John
Bạn không còn thiếu prototype ở đó? Dường như nó phải là Object.prototype.toString.call. - Brock


Đây là một câu hỏi cũ nhưng có cùng một vấn đề tôi tìm thấy một giải pháp rất tao nhã mà tôi muốn chia sẻ.

Thêm một mẫu thử nghiệm vào Array làm cho nó rất đơn giản

Array.prototype.isArray = true;

Bây giờ một lần nếu bạn có một đối tượng mà bạn muốn thử nghiệm để xem liệu một mảng của nó tất cả những gì bạn cần là kiểm tra thuộc tính mới

var box = doSomething();

if (box.isArray) {
    // do something
}

isArray chỉ khả dụng nếu một mảng của nó


49
2017-10-24 21:12



@Vitimtk Một nguyên mẫu hoạt động như một dự phòng cho đối tượng thực tế, do đó, điều này sẽ hoạt động ngay cả khi mảng trong câu hỏi đã tồn tại. Nó sẽ không hoạt động trước khi dòng nguồn được xử lý, tất nhiên. - Markus Bruckner
Giả sử không có ai Object.prototype.isArray = true;! :( - ErikE
@ErikE khiến tôi cười. this.trollcode = true - omninonsense
Lưu ý rằng trong ES5 Array.isArray là một phương pháp (ví dụ: Array.isArray([1,2,3]) === true) vì vậy @ErikE không phải là một kẻ lừa đảo. Tôi sẽ tránh làm theo câu trả lời này vì nó sẽ phá vỡ mã trong một số trình duyệt hiện đại. - JaredMcAteer
@ Ibu và bạn có thể làm {}.isArray === true với "giải pháp" của tôi, đó là toàn bộ vấn đề ... - ErikE


Thông qua Crockford:

function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (value instanceof Array) {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

Crockford không đề cập chính là không có khả năng xác định chính xác các mảng được tạo trong một ngữ cảnh khác, ví dụ: window. Trang đó có một phiên bản phức tạp hơn nhiều nếu điều này là không đủ.


45
2018-04-20 09:07





Cá nhân tôi thích đề xuất của Peter: https://stackoverflow.com/a/767499/414784 (đối với ECMAScript 3. Đối với ECMAScript 5, sử dụng Array.isArray())

Tuy nhiên, nhận xét về bài đăng cho biết rằng nếu toString() được thay đổi ở tất cả, cách kiểm tra một mảng sẽ thất bại. Nếu bạn thực sự muốn cụ thể và đảm bảo toString() chưa được thay đổi và không có vấn đề gì với thuộc tính class object ([object Array] là thuộc tính lớp của một đối tượng là một mảng), sau đó tôi khuyên bạn nên làm một cái gì đó như thế này:

//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')
    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    }
    else
    {
        // may want to change return value to something more desirable
        return -1; 
    }
}

Lưu ý rằng trong JavaScript The Definitive Guide 6th edition, 7.10, nó nói Array.isArray() được triển khai bằng Object.prototype.toString.call() trong ECMAScript 5. Cũng lưu ý rằng nếu bạn đang lo lắng về toString()thực hiện thay đổi, bạn cũng nên lo lắng về mọi phương thức khác được xây dựng trong phương pháp thay đổi quá. Tại sao sử dụng push()? Ai đó có thể thay đổi nó! Cách tiếp cận như vậy là ngớ ngẩn. Việc kiểm tra ở trên là một giải pháp được cung cấp cho những người lo lắng về toString() thay đổi, nhưng tôi tin rằng việc kiểm tra là không cần thiết.


26
2017-12-03 03:17



Lời kêu gọi tốt về tiêu chuẩn ECMAScript 5. Chắc chắn bạn không thể đảm bảo trình duyệt hỗ trợ nó nhưng đây là cách đầu tiên để kiểm tra mã mới. - styfle
Tôi sẽ bắt đầu bằng cách nói rằng đây là một chút trên đầu của tôi. Tuy nhiên, một thử nghiệm như thế này có mạnh hơn không ?: return Object.prototype.toString.call(o) === Object.prototype.toString.call([]); - Grant Lindsay