如何迭代 Object 的属性-值对?

我有一个这样的结构:

var myMap = {
partnr1: ['modelA', 'modelB', 'modelC'],
partnr2: ['modelA', 'modelB', 'modelC']
};

我将使用它们的关联(模型)迭代每个元素(partnr)。

我正在尝试双 $each()迭代来实现这一点,但什么也没有发生:

$.each(myMap, function (i, val) {
$.each(i, function (innerKey, innerValue) {


setTimeout(function () {
$('#variant').fadeOut("slow", function () {
$(this).text(innerKey + "-" + innerValue).fadeIn("slow");


});


}, i * 6000);


});
});

在使用单个值数组(Object)时,我试图实现的淡入淡出效果非常好,但是当我需要为每个键提供多个值时(如下所示)就不行了。

如何成功地完成这个迭代?在这种情况下,除了使用 Object还有其他更好的方法吗?

262951 次浏览

The callback to $.each() is passed the property name and the value, in that order. You're therefore trying to iterate over the property names in the inner call to $.each(). I think you want:

$.each(myMap, function (i, val) {
$.each(val, function(innerKey, innerValue) {
// ...
});
});

In the inner loop, given an object like your map, the values are arrays. That's OK, but note that the "innerKey" values will all be numbers.

edit — Now once that's straightened out, here's the next problem:

    setTimeout(function () {


// ...


}, i * 6000);

The first time through that loop, "i" will be the string "partnr1". Thus, that multiplication attempt will result in a NaN. You can keep an external counter to keep track of the property count of the outer map:

var pcount = 1;
$.each(myMap, function(i, val) {
$.each(val, function(innerKey, innerValue) {
setTimeout(function() {
// ...
}, pcount++ * 6000);
});
});

I'd use standard javascript:

for (var m in myMap){
for (var i=0;i<myMap[m].length;i++){
... do something with myMap[m][i] ...
}
}

Note the different ways of treating objects and arrays.

Don't use iterators to do this. Maintain your own loop by incrementing a counter in the callback, and recursively calling the operation on the next item.

$.each(myMap, function(_, arr) {
processArray(arr, 0);
});


function processArray(arr, i) {
if (i >= arr.length) return;


setTimeout(function () {
$('#variant').fadeOut("slow", function () {
$(this).text(i + "-" + arr[i]).fadeIn("slow");


// Handle next iteration
processArray(arr, ++i);
});
}, 6000);
}

Though there's a logic error in your code. You're setting the same container to more than one different value at (roughly) the same time. Perhaps you mean for each one to update its own container.

An answer to your Question from 2019:

It depends on what version of ECMAScript you use.

Pre ES6:

Use any of the answers below, e.g.:

for (var m in myMap){
for (var i=0;i<myMap[m].length;i++){
... do something with myMap[m][i] ...
}
}

For ES6 (ES 2015):

You should use a Map object, which has the entries() function:

var myMap = new Map();
myMap.set("0", "foo");
myMap.set(1, "bar");
myMap.set({}, "baz");


for (const [key, value] of myMap.entries()) {
console.log(key, value);
}

For ES8 (ES 2017):

Object.entries() was introduced:

const object = {'a': 1, 'b': 2, 'c' : 3};
for (const [key, value] of Object.entries(object)) {
console.log(key, value);
}

Functional Approach for ES6+

If you want to take a more functional approach to iterating over the Map object, you can do something like this

const myMap = new Map()
myMap.forEach((value, key) => {
console.log(value, key)
})

Well, it looks like this old JQuery thread has been coopted by ES6 Map users.

If this is what you're looking for, may I suggest using the Array.from() function which converts the Map to an Array. This allows you to easily chain transforms such as filter(), map(), etc.

const map = new Map([
['key one', 'value one'],
['key two', 'value two'],
]);


// Loop through key-value-pairs
Array.from(map.entries()).map(([key, val]) => console.log(key, val));


// Loop through map keys
Array.from(map.keys()).map(key => console.log(key));


// Loop through values
Array.from(map.values()).map(value => console.log(value));

We can use forEach Method available on maps From ES6 Version.

var myMap =new Map([
["partnr1", ['modelA', 'modelB', 'modelC']],
["partnr2", ['modelA', 'modelB', 'modelC']]
]);


myMap.forEach(function(values,key){
  

console.log(key);
  

/*****Do something with the models***********/
  

for(const [index,value] of values.entries()){
console.log(`   ${key}[${index}] : ${value}`);
}
});

This is easily achieved using a javascript Map object. You simply iterate over the Map, using the fact that the map you're iterating over is included as an argument in each iteration call. Notice the map argument in the forEach function. This is the same Map object you're iterating over.


// Define the map
const myMap = new Map([
["key1", "value 1"],
["key2": "value 2"],
["key3": "value 3"]
])


// Iterate over the map, updating each value
myMap.forEach((value,key,map) => {
map.set(key, value + "A")
})


/*
Result: myMap now looks like this:
[
["key1", "value 1A"],
["key2": "value 2A"],
["key3": "value 3A"]
]
/*