【问题标题】:Why for-in iterates through array methods also?为什么 for-in 还要遍历数组方法?
【发布时间】:2011-03-09 16:43:15
【问题描述】:

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

问题是以下还遍历了 javascript 数组对象方法并弄乱了结果查询字符串。

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'

奇怪的是,在我的本地主机空白页上它运行良好。 index.html 页面上的其他一些 javascript 会与我的代码冲突吗?如何通过仅更改我的代码(最好只更改 includedScript.js 文件)来解决冲突?

提前致谢。

【问题讨论】:

    标签: javascript arrays


    【解决方案1】:

    一个小改动:

    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 中 properties 还包括方法。


    有趣的 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]);
    }
    

    【讨论】:

    • 感谢您提供此信息,浏览器没有抛出任何错误或警告,因此我认为关联数组运行良好。如果我继续使用带有@duncan 解决方案的关联数组,会有什么缺点吗?
    • @Petr Peller 我不这么认为。但你为什么要?如果你这样做,你只使用ArrayObject 部分。请注意,您仍然可以为对象编写 $myVar['myProp']$myVar['42'],这与使用点语法相同。
    • 好吧,如果没有缺点,我为什么不使用它呢?粗略的我更喜欢使用理想的解决方案,但是在这里修改includedScript.js而不是index.html要容易得多,因为index.html中的代码在外部页面上(我无权访问它)
    • @Petr Peller 因为每件事都有它的目的。作为关联数组不是Array 对象的目的之一。我链接的文章应该告诉你更多关于为什么。如果您无法更改代码,那么您唯一的选择是使用 hack,但您应该通过添加一些来表明存在问题并且您正在 使用 hack代码中的 cmets(至少)。
    • @Petr,只是为了澄清:JavaScript 中没有关联数组,只有对象。因为一切都是对象,数组也是对象。实际上,myVar['prop'](或 myVar.prop)几乎总是可以工作,不管 myVar 是一个数组、一个布尔值、一个函数、一个字符串......(如果 myVar 为 null 或未定义,它将不起作用)。当然,正如@Alin 所说,每件事都有其目的,当常规 Object 可以完成这项工作时,您不应该使用 Array 来保存属性。
    【解决方案2】:

    你想这样做

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

    【讨论】:

    • 您可以,但您不应该这样做。在应该使用 Object 的地方使用 Array 仍然是错误的。您可以这样做的唯一原因是 Array 是 Object 的子级。
    • 确实如此。 Petr 应该同时切换到使用对象并使用 hasOwnProperty 方法。
    • 好吧,如果我切换到对象(仅将[] 更改为{}),我仍然可以将for...inhasOwnProperty 条件一起使用,它会工作吗?在这种情况下,我可以在无法修改 index.html 文件但在其他页面上使用 Object 的页面上继续使用 Array。
    • 是的,hasOwnProperty 是 Objects 上的一个函数:developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
    【解决方案3】:

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

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

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

    【讨论】:

    • 恕我直言,使用 for..in 迭代数组存在更大的问题:无法保证顺序。通常是这样,但只是巧合(我认为 for..in 属性顺序基于上次访问时间)。
    【解决方案4】:

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

    正如 Alin 提到的,对于数组使用 for (var i = 0; i

    【讨论】:

      【解决方案5】:

      这通常是使用 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]
      }
      

      哪个更有效(尤其是反转时)

      【讨论】:

      • 问题是我需要键名来构造 URL 查询部分。如果关联数组不能正常工作,我会考虑使用对象。
      • @Petr Peller JavaSript 中没有关联数组!请理解这个事实。只有对象可以用作关联数组。
      【解决方案6】:

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

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

      为了使其与旧版本的 IE 兼容,see here

      【讨论】:

      • +1 让我知道像 jQuery.each 这样的东西也存在于纯 JavaScript 中:-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 2011-02-02
      • 1970-01-01
      • 2020-05-22
      • 1970-01-01
      相关资源
      最近更新 更多