Each for object?

I have object in JavaScript:

var object = someobject;


Object { aaa=true, bbb=true, ccc=true }

How can I use each for this?

 object.each(function(index, value)) {
console.log(value);
}

Not working.

452605 次浏览

The following examples are Java, but the regex will be similar -- if not identical -- for other languages.


String target = someString.replaceAll("<[^>]*>", "");

A javascript Object does not have a standard .each function. jQuery provides a function. See http://api.jquery.com/jQuery.each/ The below should work

$.each(object, function(index, value) {
console.log(value);
});

Assuming your non-html does not contain any < or > and that your input string is correctly structured.

Another option would be to use vanilla Javascript using the Object.keys() and the Array .map() functions like this

Object.keys(object).map(function(objectKey, index) {
var value = object[objectKey];
console.log(value);
});

See https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Object/keys and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

If you know they're a specific tag -- for example you know the text contains only <td> tags, you could do something like this:

String target = someString.replaceAll("(?i)<td[^>]*>", "");

These are usually better than using a vanilla Javascript for-loop, unless you really understand the implications of using a normal for-loop and see use for it's specific characteristics like looping over the property chain.

Edit:

But usually, a for-loop doesn't work better than jQuery or Object.keys().map(). I'll go into two potential issues with using a plain for-loop below.


Ωmega brought up a good point in a comment on another post that this would result in multiple results all being squished together if there were multiple tags.

Right, so also pointed out in other answers, a plain Javascript alternative would be

for(var index in object) {
var attr = object[index];
}

For example, if the input string were <td>Something</td><td>Another Thing</td>, then the above would result in SomethingAnother Thing.

There are two potential issues with this:

In a situation where multiple tags are expected, we could do something like:

String target = someString.replaceAll("(?i)<td[^>]*>", " ").replaceAll("\\s+", " ").trim();

1 . You want to check whether the attribute that you are finding is from the object itself and not from up the prototype chain. This can be checked with the hasOwnProperty function like so

for(var index in object) {
if (object.hasOwnProperty(index)) {
var attr = object[index];
}
}

This replaces the HTML with a single space, then collapses whitespace, and then trims any on the ends.

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty for more information.

. You want to check whether the attribute that you are finding is from the object itself and not from up the prototype chain. This can be checked with the hasOwnProperty function like so

for(var index in object) {
if (object.hasOwnProperty(index)) {
var attr = object[index];
}
}

The jQuery.each and Object.keys functions take care of this automatically.

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty for more information.

2 . Another potential issue with a plain for-loop is that of scope and non-closures. This is a bit complicated, but take for example the following code. We have a bunch of buttons with ids button0, button1, button2 etc, and we want to set an onclick on them and do a console.log like this:

<button id='button0'>click</button>
<button id='button1'>click</button>
<button id='button2'>click</button>


var messagesByButtonId = {"button0" : "clicked first!", "button1" : "clicked middle!", "button2" : "clicked last!"];
for(var buttonId in messagesByButtonId ) {
if (messagesByButtonId.hasOwnProperty(buttonId)) {
$('#'+buttonId).click(function() {
var message = messagesByButtonId[buttonId];
console.log(message);
});
}
}

The jQuery.each and Object.keys functions take care of this automatically.

2 . Another potential issue with a plain for-loop is that of scope and non-closures. This is a bit complicated, but take for example the following code. We have a bunch of buttons with ids button0, button1, button2 etc, and we want to set an onclick on them and do a console.log like this:

<button id='button0'>click</button>
<button id='button1'>click</button>
<button id='button2'>click</button>


var messagesByButtonId = {"button0" : "clicked first!", "button1" : "clicked middle!", "button2" : "clicked last!"];
for(var buttonId in messagesByButtonId ) {
if (messagesByButtonId.hasOwnProperty(buttonId)) {
$('#'+buttonId).click(function() {
var message = messagesByButtonId[buttonId];
console.log(message);
});
}
}

If, after some time, we click any of the buttons we will always get "clicked last!" in the console, and never "clicked first!" or "clicked middle!". Why? Because at the time that the onclick function is executed, it will display messagesByButtonId[buttonId] using the buttonId variable at that moment. And since the loop has finished at that moment, the buttonId variable will still be "button2" (the value it had during the last loop iteration), and so messagesByButtonId[buttonId] will be messagesByButtonId["button2"], i.e. "clicked last!".

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures for more information on closures. Especially the last part of that page that covers our example.

If, after some time, we click any of the buttons we will always get "clicked last!" in the console, and never "clicked first!" or "clicked middle!". Why? Because at the time that the onclick function is executed, it will display messagesByButtonId[buttonId] using the buttonId variable at that moment. And since the loop has finished at that moment, the buttonId variable will still be "button2" (the value it had during the last loop iteration), and so messagesByButtonId[buttonId] will be messagesByButtonId["button2"], i.e. "clicked last!".

Again, jQuery.each and Object.keys().map() solve this problem automatically for us, because it provides us with a function(index, value) (that has closure) so we are safe to use both index and value and rest assured that they have the value that we expect.

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

var object = { "a": 1, "b": 2};
$.each(object, function(key, value){
console.log(key + ": " + object[key]);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

//output
a: 1
b: 2