Qual é o melhor método cruzado padrão de fato para determinar se uma variável em JavaScript é um array ou não?
Pesquisando na web há várias sugestões diferentes, algumas boas e outras inválidas.
Por exemplo, o seguinte é uma abordagem básica:
function isArray(obj) {
return (obj && obj.length);
}
No entanto, observe o que acontece se a matriz estiver vazia, ou obj realmente não for uma matriz, mas implementar uma propriedade de comprimento, etc.
Então, qual implementação é a melhor em termos de realmente funcionar, ser cross-browser e ainda ter um desempenho eficiente?
javascript
arrays
stpe
fonte
fonte
Respostas:
A verificação de tipo de objetos em JS é feita via
instanceof
, ou seja,Isso não funcionará se o objeto for passado pelos limites do quadro, pois cada quadro tem seu próprio
Array
objeto. Você pode contornar isso verificando a propriedade interna [[Class]] do objeto. Para obtê-lo, useObject.prototype.toString()
(é garantido que funcione pela ECMA-262):Ambos os métodos funcionarão apenas para arrays reais e não para objetos do tipo array, como o
arguments
objeto ou listas de nós. Como todos os objetos em forma de matriz devem ter umalength
propriedade numérica , eu verificaria assim:Observe que as strings passarão nesta verificação, o que pode causar problemas, pois o IE não permite acesso aos caracteres de uma string por índice. Portanto, você pode querer alterar
typeof obj !== 'undefined'
paratypeof obj === 'object'
para excluir primitivos e objetos de host com tipos diferentes de todos'object'
juntos. Isso ainda permitirá a passagem de objetos de string, que teriam que ser excluídos manualmente.Na maioria dos casos, o que você realmente deseja saber é se pode iterar sobre o objeto por meio de índices numéricos. Portanto, pode ser uma boa ideia verificar se o objeto tem uma propriedade chamada
0
, o que pode ser feito por meio de uma destas verificações:A conversão para o objeto é necessária para funcionar corretamente para primitivos do tipo array (ou seja, strings).
Este é o código para verificações robustas para matrizes JS:
e objetos semelhantes a array iteráveis (ou seja, não vazios):
fonte
hasOwnProperty
método, então apenas prefixe seuinstanceof
comobj.hasOwnProperty &&
; Além disso, isso ainda é um problema com o IE7? meus testes simples via gerenciador de tarefas sugerem que a memória foi recuperada após minimizar o navegador ...A chegada do ECMAScript 5th Edition nos dá o método mais seguro de testar se uma variável é uma matriz, Array.isArray () :
Embora a resposta aceita aqui funcione em frames e janelas para a maioria dos navegadores, não funciona para o Internet Explorer 7 e inferior , porque
Object.prototype.toString
uma matriz chamada de uma janela diferente retornará[object Object]
, não[object Array]
. O IE 9 também parece ter regredido a esse comportamento (consulte a correção atualizada abaixo).Se quiser uma solução que funcione em todos os navegadores, você pode usar:
Não é totalmente inquebrável, mas só seria quebrado por alguém que tentasse quebrá-lo. Ele contorna os problemas do IE7 e inferiores e do IE9. O bug ainda existe no IE 10 PP2 , mas pode ser corrigido antes do lançamento.
PS, se você não tiver certeza sobre a solução, então eu recomendo que você teste o que quiser e / ou leia a postagem do blog. Existem outras soluções possíveis se você não se sentir confortável com a compilação condicional.
fonte
isArray
não retorna verdadeiro de arrays criados em outros modos de documento? Terei de averiguar isso quando tiver algum tempo, mas acho que a melhor coisa a fazer é registrar um bug no Connect para que possa ser corrigido no IE 10.Crockford tem duas respostas na página 106 de "The Good Parts". O primeiro verifica o construtor, mas fornecerá falsos negativos em diferentes frames ou janelas. Aqui está o segundo:
Crockford aponta que esta versão identificará o
arguments
array como um array, mesmo que não tenha nenhum dos métodos de array.Sua interessante discussão do problema começa na página 105.
Há mais uma discussão interessante (pós-boas peças) aqui que inclui esta proposta:
Toda a discussão me faz nunca querer saber se algo é ou não um array.
fonte
jQuery implementa uma função isArray, que sugere que a melhor maneira de fazer isso é
(snippet retirado do jQuery v1.3.2 - ligeiramente ajustado para fazer sentido fora do contexto)
fonte
Object.prototype.toString()
- isso é menos provável de quebrarRoubando do guru John Resig e jquery:
fonte
typeof
são padronizados?O que você vai fazer com o valor depois de decidir que é uma matriz?
Por exemplo, se você pretende enumerar os valores contidos, se parecer uma matriz OU se for um objeto sendo usado como uma tabela hash, o código a seguir obtém o que você deseja (este código para quando a função de fechamento retorna qualquer outro do que "indefinido". Observe que ele NÃO itera em contêineres COM ou enumerações; isso é deixado como um exercício para o leitor):
(Observação: "o! = Null" testa tanto para nulo quanto para indefinido)
Exemplos de uso:
fonte
for..in
é ruim [tm])for..in
itera sobre propriedades enumeráveis de objetos; você não deve usá-lo com arrays porque: (1) é lento; (2) não há garantia de preservação da ordem; (3) incluirá qualquer propriedade definida pelo usuário configurada no objeto ou qualquer um de seus protótipos, já que ES3 não inclui nenhuma forma de configurar o atributo DontEnum; pode haver outros problemas que passaram pela minha menteSe você estiver fazendo isso no CouchDB (SpiderMonkey), use
Array.isArray(array)
como
array.constructor === Array
ouarray instanceof Array
não funcionam. Usararray.toString() === "[object Array]"
funciona, mas parece muito duvidoso em comparação.fonte
Se você quiser um navegador cruzado, deve jQuery.isArray .
fonte
No w3school, há um exemplo que deve ser bastante padrão.
Para verificar se uma variável é uma matriz, eles usam algo semelhante a este
testado no Chrome, Firefox, Safari, ie7
fonte
constructor
para verificação de tipo é muito frágil; em vez disso, use uma das alternativas sugeridasconstructor
é uma propriedade DontEnum regular do objeto protótipo; isso pode não ser um problema para tipos integrados, desde que ninguém faça nada estúpido, mas para tipos definidos pelo usuário pode ser facilmente; meu conselho: sempre useinstanceof
, que verifica a cadeia de protótipo e não depende de propriedades que podem ser substituídas arbitrariamenteUma das versões mais pesquisadas e discutidas dessa função pode ser encontrada no site do PHPJS . Você pode criar um link para pacotes ou ir diretamente para a função . Eu recomendo fortemente o site para equivalentes bem construídos de funções PHP em JavaScript.
fonte
Referência insuficiente igual aos construtores. Às vezes, eles têm diferentes referências de construtor. Então, eu uso representações de string deles.
fonte
{constructor:{toString:function(){ return "function Array() { [native code] }"; }}}
Substituir
Array.isArray(obj)
porobj.constructor==Array
amostras:
Array('44','55').constructor==Array
retornar verdadeiro (IE8 / Chrome)'55'.constructor==Array
retornar falso (IE8 / Chrome)fonte