Loop foreach Javascript no objeto de matriz associativa

182

Por que meu loop for-for-it não está repetindo meu objeto de matriz associativa JavaScript?

// defining an array
var array = [];

// assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";

// expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var i = 0; i < array.length; i++) {
    console.log(array[i]);
}

EDIT: jQuery each()pode ser útil: https://api.jquery.com/jQuery.each/

Szymon Toda
fonte
1
Você cria uma matriz, mas depois a usa como um mapa. Parece que você deseja um objeto simples.
Jon
4
Não existem coisas como associative arraysem JS: é uma matriz simples ou um objeto. Nada impede a adição de propriedades não numéricas Array, mas isso não acontece associative- em particular, a lengthpropriedade não conta automaticamente essas propriedades.
precisa saber é o seguinte
3
re: Não existem matrizes associativas em JS. - redigido de outra maneira: o JavaScript usa o nome "Objeto" em vez do nome "matriz associativa". Mas não possui uma propriedade ".length".
Jesse Chisholm

Respostas:

315

A .lengthpropriedade rastreia apenas propriedades com índices numéricos (chaves). Você está usando cadeias de caracteres para chaves.

Você consegue fazer isso:

var arr_jq_TabContents = {}; // no need for an array

arr_jq_TabContents["Main"] = jq_TabContents_Main;
arr_jq_TabContents["Guide"] = jq_TabContents_Guide;
arr_jq_TabContents["Articles"] = jq_TabContents_Articles;
arr_jq_TabContents["Forum"] = jq_TabContents_Forum;

for (var key in arr_jq_TabContents) {
    console.log(arr_jq_TabContents[key]);
}

Para estar seguro, é uma boa ideia em loops assim garantir que nenhuma das propriedades seja resultado inesperado da herança:

for (var key in arr_jq_TabContents) {
  if (arr_jq_TabContents.hasOwnProperty(key))
    console.log(arr_jq_TabContents[key]);
}

editar - provavelmente é uma boa idéia agora observar que a Object.keys()função está disponível em navegadores modernos e no Nó etc. Essa função retorna as teclas "próprias" de um objeto, como uma matriz:

Object.keys(arr_jq_TabContents).forEach(function(key, index) {
  console.log(this[key]);
}, arr_jq_TabContents);

A função de retorno de chamada passada para .forEach()é chamada com cada tecla e o índice da chave na matriz retornado por Object.keys(). Também passou a matriz através da qual a função está iterando, mas essa matriz não é realmente útil para nós; precisamos do objeto original . Isso pode ser acessado diretamente pelo nome, mas (na minha opinião) é um pouco melhor passá-lo explicitamente, o que é feito passando um segundo argumento para .forEach()- o objeto original - que será vinculado como thisdentro do retorno de chamada. (Só vi que isso foi observado em um comentário abaixo.)

Pontudo
fonte
O que é isso var arr_jq_TabContents = {};? Quero dizer {}
Szymon Toda
1
@ Ultra é um objeto vazio literal. Significa apenas que a variável é inicializada com uma referência a um novo objeto vazio.
Pointy
@ Ultra, você não precisa de uma instância Array, porque nesse código você não a está usando como uma matriz JavaScript. O JavaScript não possui "matrizes associativas", como alguns outros idiomas.
Pointy
1
Qual é a diferença entre atribuir []e {}? Apenas os diferentes protótipos?
SoonDead
8
Em vez de usar o hasOwnProperty, deve ser possível em todos os navegadores da web modernos iterar sobre as chaves de um objeto usando: Object.keys(arr_jq_TabContents).forEach( function(key) { ... } );
Gregory Bell
80

Essa é uma abordagem muito simples. A vantagem é que você também pode obter as chaves:

for (var key in array) {
    var value = array[key];
    console.log(key, value);
}

Para ES6:

array.forEach(value => {
  console.log(value)
})  

Para ES6: (se você deseja valor, índice e a própria matriz)

array.forEach((value, index, self) => {
  console.log(value, index, self)
})  
tika
fonte
12
Não use varem loops sugerindo escopo que não existe. Use varna frente do loop ou letno loop.
ceving 08/12/15
2
@ ceving, você pode explicar mais sobre por que não usar var em loops? Eu venho de C ++ / PHP background e não entendo isso. O escopo existe no loop, mas é temporário, então não sei o que você quer dizer.
Dennis
6
@Dennis Na maioria dos idiomas, uma declaração variável em um forloop gera um escopo limitado ao corpo do forloop. Porém, no JavaScript, uma variável declarada por varsempre funciona como global, mesmo que você a escreva em forloop. Veja aqui: davidwalsh.name/for-and-against-let
ceving 5/08/16
1
não vazamentos de memória em si, mas definitivamente "vazamentos de memória". varem Javascript cria variáveis ​​na memória mesmo depois que o loop é concluído.
ahnbizcad
Eu acho que o objetivo desses comentários sobre o uso de "var" é agora usar "let" em geral, mas especificamente em um loop. Os motivos estão explicados acima, mas, em resumo, é devido ao escopo, "var" cria escopo global.
DeeZone
6

Já existem alguns exemplos simples, mas noto que, como você formulou sua pergunta, você provavelmente provém de um background em PHP e espera que o JavaScript funcione da mesma maneira - isso não acontece. Um PHP arrayé muito diferente de um JavaScript Array.

No PHP, uma matriz associativa pode fazer a maior parte do que uma matriz indexada numericamente (as array_*funções funcionam, você pode count(), etc.) Você simplesmente cria uma matriz e começa a atribuir a índices de string em vez de numéricos.

No JavaScript, tudo é um objeto (exceto os primitivos: string, numérico, booleano) e as matrizes são uma certa implementação que permite que você tenha índices numéricos. Qualquer coisa empurrado para uma matriz vai efectuar a sua length, e pode ser iterada usando métodos Array ( map, forEach, reduce, filter, find, etc.) No entanto, porque tudo é um objeto, você está sempre livre para simplesmente propriedades atribuir, porque isso é algo que você faz para qualquer objeto. A notação entre colchetes é simplesmente outra maneira de acessar uma propriedade, portanto, no seu caso:

array['Main'] = 'Main Page';

é realmente equivalente a:

array.Main = 'Main Page';

Pela sua descrição, meu palpite é que você deseja uma 'matriz associativa', mas para JavaScript, este é um caso simples de usar um objeto como um mapa de hash. Além disso, eu sei que é um exemplo, mas evite nomes sem significado que descrevam apenas o tipo de variável (por exemplo array) e o nome com base no que ela deve conter (por exemplo pages). Objetos simples não têm muitas boas maneiras diretas de iterar; portanto, muitas vezes nos transformaremos em matrizes primeiro usando Objectmétodos ( Object.keysneste caso - há também entriese valuesestão sendo adicionados a alguns navegadores agora) que podemos fazer loop.

// assigning values to corresponding keys
const pages = {
  Main: 'Main page',
  Guide: 'Guide page',
  Articles: 'Articles page',
  Forum: 'Forum board',
};

Object.keys(pages).forEach((page) => console.log(page));
Josh de Qaribou
fonte
4

arr_jq_TabContents[key] vê a matriz como um formulário com índice 0.

MSO
fonte
4

Aqui está uma maneira simples de usar uma matriz associativa como um tipo de objeto genérico:

Object.prototype.forEach = function(cb){
   if(this instanceof Array) return this.forEach(cb);
   let self = this;
   Object.getOwnPropertyNames(this).forEach(
      (k)=>{ cb.call(self, self[k], k); }
   );
};

Object({a:1,b:2,c:3}).forEach((value, key)=>{ 
    console.log(`key/value pair: ${key}/${value}`);
});

Chouettou
fonte
1

Isso é (essencialmente) incorreto na maioria dos casos:

var array = [];
array["Main"] = "Main page";

Isso cria uma propriedade não-elemento na matriz com os nomes Main. Embora matrizes sejam objetos, normalmente você não deseja criar propriedades que não sejam de elementos.

Se você deseja indexar arraypor esses nomes, normalmente usaria um Mapou um objeto simples, não uma matriz.

Com um Map(ES2015 +), que chamarei de mapcriativo:

let map = new Map();
map.set("Main", "Main page");

Você, então, iterar-lo usando os iteradores de seus values, keysou entriesmétodos, por exemplo:

for (const value of map.values()) {
    // Here, `value` will be `"Main page"`, etc.
}

Usando um objeto simples, que chamarei de forma criativa obj:

let obj = Object.create(null); // Creates an object with no prototype
obj.Main = "Main page"; // Or: `obj["Main"] = "Main page";`

você iria em seguida, iterar seu conteúdo usando Object.keys, Object.valuesou Object.entries, por exemplo:

for (const value of Object.values(proches_X)) {
    // Here, `value` will be `"Main page"`, etc.
}
TJ Crowder
fonte
0

var obj = {
  no: ["no", 32],
  nt: ["no", 32],
  nf: ["no", 32, 90]
};

count = -1; // which must be static value
for (i in obj) {
  count++;
  if (obj.hasOwnProperty(i)) {
    console.log(obj[i][count])
  };
};

Neste código, usei o método brackets para valores de chamada na matriz porque ela continha matriz, no entanto, brevemente, a ideia de que uma variável i tem uma chave de propriedade e com um loop chamado ambos os valores da matriz associada

Método perfeito, se você estiver interessado, pressione como

Dev-Wb Ahmed
fonte
Você não está repetindo um array, mas sim um objeto que possui matrizes em suas chaves. Por favor, leia a pergunta e veja o exemplo.
Pedro Joaquín
0

Você consegue fazer isso

var array = [];

// assigning values to corresponding keys
array[0] = "Main page";
array[1] = "Guide page";
array[2] = "Articles page";
array[3] = "Forum board";


array.forEach(value => {
    console.log(value)
})
Shuvro
fonte