代码之家  ›  专栏  ›  技术社区  ›  Anurag

当排序很重要时,使用for..in迭代javascript对象属性和数组。

  •  3
  • Anurag  · 技术社区  · 15 年前

    这已经是个年纪了 question 我知道不使用的常见原因。 for..in or perhaps even objects when any sort of ordering is needed, but I recently came across this article from MDC 在“删除”操作符上。

    跨浏览器问题

    尽管ecmascript使对象实现的迭代顺序依赖,但似乎所有主要浏览器都支持基于最早添加的属性(至少对于原型上没有的属性)的迭代顺序。However, in the case of Internet Explorer, when one uses delete on a property, some confusing behavior results, preventing other browsers from using simple objects like object literals as ordered associative arrays. 在资源管理器中,虽然确实将属性值设置为未定义,但如果稍后再添加一个同名的属性,则该属性将在其旧位置进行迭代,而不是在迭代序列的末尾,正如在删除该属性并将其添加回后所预期的那样。

    因此,如果要在跨浏览器环境中模拟有序的关联数组,则必须使用两个单独的数组(一个用于键,另一个用于值),或者构建单个属性对象的数组等。

    大多数主要浏览器(Chrome、Safari、Firefox和Opera)似乎都按插入顺序枚举对象属性。这是一个快速 test 在…中 假设我们 不要删除任何东西 from the object?

    也, 在…中 never 推荐用于重复数组的原因完全相同,事实上 Array.prototype is more commonly tampered with than Object.prototype . 但是,如果属性实际上是按插入顺序枚举的,那么我想 在…中 也可以用于循环数组,下面列出了以下属性 原型 will be enumerated as well.

    There are two solutions to this:

    Check if property belongs to the object using hasOwnProperty

    for(var index in object) {
        if(object.hasOwnProperty(index)) {
            ..
        }
    }
    

    Use the new ES5 syntax for defining properties on objects and make them non-enumerable. This assumes that you have full control over the extension to base prototypes, and no 3rd party code adds anything on the prototype directly.

    Object.defineProperty(Array.prototype, "size", {
        enumerable: false,
        configurable: false,
        get: function() { return this.length; },
        set: undefined
    });
    

    If all the above conditions are met, and unless I am missing something crucial, 在…中 can be safely used for array iteration as well:

    var values = [1, 2, 3];
    
    for(var i in values) {
        values[i];
    }
    

    所以我想这又回到了最初的问题。不管规范怎么说,对于任何版本,IE是否支持按插入顺序进行对象迭代?还有其他浏览器不支持这个功能吗?

    3 回复  |  直到 14 年前
        1
  •  4
  •   gblazex    15 年前

    Tests on IE 5.5-6-7-8 showed the exact same behavior. The properties are ordered. The deleted property keeps its position.

    但由于这是非标准行为,它可能会与IE9或任何浏览器的下一个版本发生冲突…

    也许我错过了什么,但有什么意义?与更健壮的代码相比,节省一些字符,这与第三方广告、跟踪系统、小工具等运行良好?

    更不用说支持移动浏览器,以及市场份额很小的桌面浏览器了。

        2
  •  3
  •   Tim Down    14 年前

    浏览器比这里提到的要多:还有其他的当前浏览器和未来的浏览器。它们中没有一个必须在迭代对象属性时实现任何排序,并且不会很长时间,因为最近的ecmascript 5没有指定任何排序。的确, Chrome development team is refusing to change its implementation 尽管有声音要求使其与其他浏览器保持一致。

    基于观察到的当前浏览器行为的任何假设充其量都是不可靠的;正如观察到的,并非所有当前浏览器的行为都相同,未来的浏览器可能选择不符合您的假设,并有权这样做。因此,我强烈建议不要依赖于任何代码中的任何特定排序。

        3
  •  1
  •   maerics    15 年前

    在winxp pro sp2上的ie8上运行测试可以确认mdc文章。IE8按声明的顺序迭代成员;如果删除现有属性,然后重新分配,则保持其原始迭代位置。其他浏览器(我验证了chrome 5和firefox 3)将重新分配的属性放在迭代顺序的末尾。