Javascript for..in looping over arguments ie.for (arg argument) doesn't work in IE8, but works in Chrome 8

I came across this strange situation where foreach like javascript construct does not work in IE, but works in FF. Well, not all for..in only this special function does not work. I will send the code. Tested in IE8. Tested also with DTD XHTML.

  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> Test </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> </HEAD> <script type="text/javascript"> <!-- String.prototype.format = function() { var formatted = this; var mycars = new Array(); //some mycars[0] = "Saab"; mycars[1] = "Volvo"; mycars[2] = "BMW"; var arg; for (arg in mycars) { alert('it comes here'); formatted = formatted.replace("{" + arg + "}", arguments[arg]); } return formatted; }; String.prototype.format2 = function() { var formatted = this; var arg; for (arg in arguments) { alert('it does not come here'); formatted = formatted.replace("{" + arg + "}", arguments[arg]); } return formatted; }; function fn() { var s = 'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP'); alert('format:'+s); var s2 = 'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format2('ASP', 'PHP'); alert('format2:'+s2); //does not replace {0}s and {1}s } //--> </script> <BODY> <input type="button" value="click " onclick="fn();" /> </BODY> </HTML> 

Update . I asked the wrong question that it works in FireFox, but not in IE8, which was incorrect. It also does not work in FireFox. Actually, I got this code from post JavaScript, equivalent to printf / string.format .

+8
javascript internet-explorer foreach arguments
source share
5 answers

First of all, although the arguments object, accessible within the function, is not an array, it is rather "similar to an array", which is preferable to the increment for the loop ( for (var i = 0, len = arguments.length; i < len; i++) { ... } ) - not only because it works faster, but also because it avoids other traps - one of which is exactly what you fall into.

To answer the question of why the second loop does not work, it is important to understand what exactly ... in the loop: it iterates through all the listed properties found in the object. Now I have highlighted 2 words in this statement because I used these two words purposefully to indicate a couple of nuances that, although they may seem subtle, can dramatically affect the behavior of your code if you do not understand what is happening.

First, let's focus on everything that I have in mind, not only the properties of the object itself, but also potentially the properties that this object inherited from its prototype or prototype prototype or so on. For this reason, it is often recommended that you "guard" any of ... in the loop, adding in addition its qualifications with the condition if (obj.hasOwnProperty(p)) (assuming your loop was written for (var p in obj) )

But that is not what you are doing here. To do this, let me focus on this second word enumerable . All object properties in JavaScript are enumerable or not enumerated, which is largely directly related to whether the property appears in the for for ... in loop or not. As it turned out, in browsers such as Firefox and IE, the numeric properties of the arguments object are not listed (nor its length ), which is why you are not iterating through anything!

But in fact, in the end, to iterate through everything that is an array or an array, you better use an incremental loop (as M. Kolodny pointed out) and generally avoid these frauds (not to mention the potential of cross-browser inconsistencies - I seem to notice that in Chrome 10 the numeric properties of arguments objects are listed!)

+23
source share

Try using this as a function of the format:

 String.prototype.format = function() { var me = this; for (var i = 0; i < arguments.length; i++) me = me.replace(new RegExp('\\{' + i + '\\}', 'g'), arguments[i]); return me; } 

Now this should work:

 alert('The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP')) 

Demo

Tested and works in IE

+2
source share

From my test, with Firefox 3.6.13 and IE 8, I see no difference in behavior, both of them are not included in the second cycle.

One of the differences between mycars and arguments is that mycars is an array and arguments is an object.

To demonstrate this:

 alert(mycars.constructor); //shows: "function Array() { [native code] }" alert(arguments.constructor); //shows: "function Object() { [native code] }" 

However, with some test code, I see that "for in" works for Array and Object

 var showWithForIn = function (myArgument) { for (i in myArgument) { alert(myArgument[i]); } }; var testArray = function() { var mycars = new Array(); //some mycars[0] = "Saab"; mycars[1] = "Volvo"; mycars[2] = "BMW"; showWithForIn(mycars); }; var testObject = function() { var myFriends = { 0: 'John', 1: 'Aileen' }; showWithForIn(myFriends); }; function testAll() { testArray(); testObject(); } 

So I'm not sure how the arguments of Object differ from the object you create yourself with sticky curly braces. I think this is confusing because in this test to work for both an array and an object. Although "for in" does not work with arguments.

Again, in all tests, I did not notice any difference between FF 3.6 and IE 8.

UPDATE . As I learned from Ken's comments, the properties of the arguments are defined as non-enumerable, while when defining the properties of a literal, Objects are implicitly defined as enumerated.

0
source share

Some browsers support for..in , such as Chrome and Firefox 4, for repeating arguments, but other browsers do not see its parameters during iteration. I am sure that in these browsers, if you made JSON.stringify (arguments), the result will be an empty object. According to the specification, JavaScript 1.1 and further arguments have a length parameter, so you can iterate them using for (var i = 0; i < arguments.length; i++) and while(i < arguments.length) loops.

Personally, as soon as I was burned with for..in to argue the iteration, I wrote a simple function to iterate the object of the argument, which does not depend on the length, because the arguments are always marked in order by identifiers.

 var eachArg = function(args, fn, start_from, end_where) { var i = start_from || 0; while (args.hasOwnProperty(i)) { if (end_where !== undefined && i === end_where) return i; if (fn !== undefined) fn(i, args[i]); i++; } return i; }; 

I have been using it since when I repeat the arguments, and that does not fail me. Read more about this on my blog post http://stamat.wordpress.com/iterating-arguments-in-javascript/

0
source share

Well, it should work, so if it’s not, the answer is as simple as β€œthis is another mistake in IE”.

But the real question is why are you using for ... in to iterate through arrays or objects like array (e.g. arguments ) - just use a simple for loop that works in all major browsers:

 for (var i = 0; i < arguments.length; i++) { // do something with arguments[i] } 
-2
source share

All Articles