Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why for-in iterates through array methods also?

on a page I use similar syntax to google analitycs code, to pass parameters to another script. I iterate through the array and try to construct query part of URL according to the parameters in the included script.

The problem is the following iterates through the javascript array objects methods also and mess up resulting queryString.

index.html:

<script>
    var params = [];
    params['first'] = '1';
    params['second'] = '2';

    (function() {
          var vs = document.createElement('script');
          vs.async = true; vs.type = 'text/javascript';
          vs.src = 'http://my.domain.com/js/includedScript.js';
          var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(vs, s);
    })();
</script>

includedScript.js:

function(paramsArray) {
   tmpArray = [];
   for(i in paramsArray) {
      tmpArray.push(i + '=' + escape(paramsArray[i]));
   }
   var queryString = tmpArray.join('&');
}(params);

I got (shortened):

queryString == 'first=1&second=2&push&$family=function%20%28%29%20%7B%0A%20%20%20%20return%20lower%3B%0A%7D&$constructor=function%20Array%28%29%20%7B%0A%20%20%20%20%5Bnative%20code%5D%0A%7D&pop=function%20pop%28%29%20%7B%0A%20%20%20%20%5Bnative%20code%5D%0A%7D&push=function%20push%28%29%20%7B%0A%'

I expect:

queryString == 'first=1&second=2'

It's strange, that on my localhost blank page it's working well. Could some other javascript on the index.html page collide with my code? How can I fix the collision by changing only my code (preferably only the includedScript.js file)?

Thanks in advance.

like image 654
Petr Peller Avatar asked Jun 13 '26 14:06

Petr Peller


1 Answers

One small change:

var params = {}; // notice the difference here!
params['first'] = '1';
params['second'] = '2';

and another one here

for(i in paramsArray) {
  if(paramsArray.hasOwnProperty(i)){
    tmpArray.push(i + '=' + escape(paramsArray[i]));
  }
}

JavaScript's Array should only be used with numeric indexes. For associative arrays use Object instead. Also to make sure that the properties you get were added by you and do not belong to the a prototype use hasOwnProperty.

See the documentation on mozilla.org for more info.

An array is an ordered set of values associated with a single variable name. Note that you shouldn't use it as an associative array, use Object instead.

Also you could read this article: http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/


Note: The for ... in JavaScript construct has no connection with Array. Its purpose is to iterate over Object properties, not Array elements. In JavaScript properties also include methods.


Fun with JavaScript.

Try the following code and tell me if you're surprised:

var x = [];
x['one'] = 1;
x['one'] = 2;
alert(x.length);

then try this one:

Object.prototype.myProp = 123;
var x = {one: 1, two: 2}
for(var prop in x){
  alert(x[prop]);
}
like image 100
Alin Purcaru Avatar answered Jun 15 '26 03:06

Alin Purcaru