为什么for-in也会遍历数组方法?

时间:2011-03-09 16:43:15

标签: javascript arrays

在页面上我使用类似的语法google analitycs代码,将参数传递给另一个脚本。我遍历数组并尝试根据所包含脚本中的参数构造URL的查询部分。

问题是以下迭代遍历javascript数组对象的方法也搞砸了生成的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);

我得到了(缩短):

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%'

我期待:

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

奇怪的是,在我的localhost空白页面上,它运行良好。 index.html页面上的其他一些javascript是否会与我的代码发生冲突?如何通过仅更改我的代码(最好只更改includedScript.js文件)来修复冲突?

提前致谢。

6 个答案:

答案 0 :(得分:5)

一个小小的变化:

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

另一个在这里

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

JavaScript Array只应与数字索引一起使用。对于关联数组,请改用Object。另外,要确保您获得的属性是由您添加的,并且不属于原型,请使用hasOwnProperty

有关详细信息,请参阅the documentation on mozilla.org

  

数组是一组有序的值   与单个变量相关联   名称。请注意,您不应该使用它   作为关联数组,使用Object   代替。

你也可以阅读这篇文章: http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/


注意:for ... in JavaScript构造与Array没有关联。其目的是迭代Object属性,而不是Array元素。在JavaScript中,属性也包含方法。


有趣的JavaScript。

尝试以下代码并告诉我您是否感到惊讶:

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

然后尝试这个:

Object.prototype.myProp = 123;
var x = {one: 1, two: 2}
for(var prop in x){
  alert(x[prop]);
}

答案 1 :(得分:4)

你想这样做

for (i in paramsArray) {
    if (paramsArray.hasOwnProperty(i)) {
        ....
    }
}

答案 2 :(得分:1)

您不应该使用for..in来遍历数组元素。事物可以自动原型化到对象上以利用DOM方法或通过页面上的其他javascript编程(如原型设计)。

您应该使用.length和正常for循环获取数组元素的计数。

var l = paramsArray.length;
for (var c = 0; c < l; c++) {
  // do stuff
} 

答案 3 :(得分:1)

使用for...in进行循环时,这通常是一个问题,这是从未真正推荐过的。

解决方法是使用.hasOwnProperty()方法确保获得自己的变量:

for (var k in foo) {
    if (foo.hasOwnProperty(k)) {
       // do something with foo[k]
    }
}

或者正如其他人所建议的那样,使用常规for循环:

for(var k = foo.lenght-1; k >= 0; --k) {
    // do something with foo[k]
}

哪种效率更高(特别是在逆转时)

答案 4 :(得分:1)

duncan的回答是正确的,那是因为for-in循环将paramsArray视为对象,而不是数组。

正如Alin所提到的,对数组使用(var i = 0; i&lt; paramsArray.length; i ++)。

答案 5 :(得分:1)

我爱Array.forEach()。它需要一个函数作为参数。该函数接收元素,索引和原始列表作为参数。

["a","b","c"].forEach(function(item, index, list)
{
     console.log("the item at index " + index + " is " + item);
});

使其与早期版本的IE兼容,see here