Eu usei JSLint em um arquivo JavaScript meu. Ele lançou o erro:
for( ind in evtListeners ) {
Problema na linha 41, caractere 9: o corpo de um for for deve ser envolvido em uma instrução if para filtrar propriedades indesejadas do protótipo.
O que isto significa?
javascript
jslint
jrharshath
fonte
fonte
if (evtListeners.hasOwnProperty(ind))
para restringir o processamento apenas às propriedades (não herdadas). Ainda assim, em alguns casos, você realmente deseja iterar sobre todas as propriedades, incluindo as herdadas. Nesse caso, o JSLint obriga a envolver o corpo do loop em uma instrução if para decidir quais propriedades você realmente deseja. Isto irá funcionar e fazer JSLint feliz:if (evtListeners[ind] !== undefined)
Respostas:
Primeiro de tudo, nunca use um
for in
loop para enumerar sobre uma matriz. Nunca. Use bom e velhofor(var i = 0; i<arr.length; i++)
.A razão por trás disso é o seguinte: cada objeto em JavaScript tem um campo especial chamado
prototype
. Tudo o que você adicionar a esse campo estará acessível em todos os objetos desse tipo. Suponha que você deseje que todas as matrizes tenham uma nova função interessante chamadafilter_0
que filtrará os zeros.Essa é uma maneira padrão de estender objetos e adicionar novos métodos. Muitas bibliotecas fazem isso. No entanto, vamos ver como
for in
funciona agora:Você vê? De repente, pensa que filter_0 é outro índice de matriz. Obviamente, não é realmente um índice numérico, mas
for in
enumera através de campos de objetos, não apenas índices numéricos. Então, agora estamos enumerando todos os índices numéricos efilter_0
. Masfilter_0
não é um campo de nenhum objeto de matriz específico, todo objeto de matriz possui essa propriedade agora.Felizmente, todos os objetos têm um
hasOwnProperty
método que verifica se esse campo realmente pertence ao próprio objeto ou se é simplesmente herdado da cadeia de protótipos e, portanto, pertence a todos os objetos desse tipo.Note que embora este código funciona como esperado para arrays, você não deve nunca, nunca mais , o uso
for in
efor each in
para arrays. Lembre-se de quefor in
enumera os campos de um objeto, não os índices ou valores da matriz.fonte
for in
para iterar sobre matrizes porque o idioma não exige a ordem na qualfor in
a enumeração será feita sobre uma matriz. Pode não estar em ordem numérica. Além disso, se você usar a construção de estilo `for (i = 0; i <array.length; i ++), poderá ter certeza de que está apenas repetindo os índices numéricos na ordem e sem propriedades alfanuméricas.for-in
loops (o que é incrível, a propósito), devemos educá-los como eles funcionam (feitos corretamente nesta resposta) e apresentá-los paraObject.defineProperty()
que eles possam estender seus protótipos com segurança sem quebrar nada. Aliás, a extensão dos protótipos de objetos nativos não deve ser feita semObject.defineProperty
.Douglas Crockford, autor de jslint, escreveu (e falou) sobre esse assunto muitas vezes. Há uma seção nesta página do site dele que cobre isso:
Crockford também tem uma série de vídeos no teatro YUI, onde ele fala sobre isso. A série de vídeos / palestras de Crockford sobre javascript é imperdível se você é levemente sério sobre javascript.
fonte
Ruim: (jsHint lançará um erro)
Boa:
fonte
A resposta da Vava está na marca. Se você usa jQuery, a
$.each()
função cuida disso, portanto, é mais seguro de usar.fonte
$.each
(ou underscore.js_.each
) se você puder se safar dofor
loop bruto . O jsperf tem alguns testes de comparação que valem a pena ser executados.@all - tudo no JavaScript é um objeto (), então declarações como "use isso apenas em objetos" são um pouco enganadoras. Além disso, o JavaScript não é fortemente digitado, de forma que 1 == "1" é verdadeiro (embora 1 === "1" não seja, Crockford é importante nisso). Quando se trata do conceito programático de matrizes em JS, a digitação é importante na definição.
@Brenton - Não há necessidade de ser um ditador de terminologia; "matriz associativa", "dicionário", "hash", "objeto", todos esses conceitos de programação se aplicam a uma estrutura em JS. É o nome (chave, índice) pares de valores, onde o valor pode ser qualquer outro objeto (cadeias também são objetos)
Então,
new Array()
é o mesmo que[]
new Object()
é aproximadamente semelhante a{}
Cria uma estrutura que é uma matriz com a restrição de que todos os índices (também conhecidos como chaves) devem ser um número inteiro. Também permite a atribuição automática de novos índices via .push ()
É realmente melhor tratado via
for(initialization;condition;update){
Mas e quanto a:
Tente o seguinte:
Talvez não seja o melhor uso de uma matriz, mas apenas uma ilustração de que as coisas nem sempre são claras.
Se você conhece suas chaves e, definitivamente, se elas não são números inteiros, sua única opção de estrutura como matriz é o objeto.
fonte
Certamente é um pouco extremo dizer
?
Vale destacar a seção no extrato de Douglas Crockford
Se você precisar de uma matriz associativa (também conhecida como hashtable / dictionary) em que as chaves sejam nomeadas em vez de indexadas numericamente, será necessário implementá-la como um objeto, por exemplo
var myAssocArray = {key1: "value1", key2: "value2"...};
.Nesse caso,
myAssocArray.length
será nulo (porque esse objeto não possui uma propriedade 'length') e vocêi < myAssocArray.length
não o levará muito longe. Além de proporcionar maior conveniência, eu esperaria que matrizes associativas ofereçam vantagens de desempenho em muitas situações, pois as chaves da matriz podem ser propriedades úteis (ou seja, propriedade ou nome do ID de um membro da matriz), o que significa que você não precisa iterar por um longo tempo. matriz avaliando repetidamente as instruções if para encontrar a entrada da matriz que você procura.De qualquer forma, obrigado também pela explicação das mensagens de erro do JSLint, vou usar a verificação 'isOwnProperty' agora ao interagir através de minhas inúmeras matrizes associativas!
fonte
length
propriedade, mas você pode fazê-lo de outra forma:var myArr = []; myArr['key1'] = 'hello'; myArr['key2'] = 'world';
var myArr = []
la.var myArr = {}
No PHP, elas são a mesma coisa, mas não no JS.Isso significa que você deve filtrar as propriedades de evtListeners com o método hasOwnProperty .
fonte
Apenas para adicionar ao tópico de em / para / $. Each, adicionei um caso de teste jsperf para usar $ .each vs for em: http://jsperf.com/each-vs-for-in/2
Diferentes navegadores / versões lidam com isso de maneira diferente, mas parece que $ .each e diretamente para in são as opções mais baratas em termos de desempenho.
Se você estiver usando o for para iterar através de um array / objeto associativo, sabendo o que está procurando e ignorando tudo o mais, use $ .each se usar o jQuery ou apenas para o in (e depois uma pausa; alcançou o que você sabe que deveria ser o último elemento)
Se você estiver iterando através de uma matriz para executar algo com cada par de chaves, deve usar o método hasOwnProperty se NÃO usar o jQuery e usar $ .each se usar o jQuery.
Sempre use
for(i=0;i<o.length;i++)
se você não precisar de uma matriz associativa ... lol chrome executou 97% mais rápido do que um para dentro ou$.each
fonte