Node.js库依赖于对象键顺序是否可以接受?

时间:2012-02-07 16:12:44

标签: javascript node.js

枚举javascript对象的键按插入顺序重放键:

> for (key in {'z':1,'a':1,'b'}) { console.log(key); }
z
a
b

这不是标准的一部分,但已广泛实施(如here所述):

  

ECMA-262未指定枚举顺序。事实上的标准是匹配   插入顺序,V8也可以,但有一个例外:

     

V8不保证数组索引的枚举顺序(即属性)   可以解析为32位无符号整数的名称。

构建Node.js库时依赖此行为是否可以接受?

4 个答案:

答案 0 :(得分:13)

绝对不是!这不是风格的问题,而是正确性

如果你依赖这个“事实上的”标准,你的代码可能会在ECMA-262 5th Ed上失败。兼容的解释器,因为该规范没有指定枚举顺序。此外,V8引擎可能在未来改变其行为,例如为了性能,例如

答案 1 :(得分:7)

绝对不依赖按键的顺序。如果标准没有指定订单,那么实现可以随意执行。散列表通常是这些对象的基础,你无法知道何时可以使用它们。 Javascript有很多实现,它们都是竞争最快的。如果不是现在,那么密钥顺序将在实现之间变化,然后在将来。

答案 2 :(得分:1)

没有。依靠ECMAScript标准,或者您必须与开发人员争论是否存在“事实上的标准”,就像那个bug上的人一样。

答案 3 :(得分:0)

不建议天真地依靠它。

您还应该尽最大努力遵守规范/标准。

但是,在很多情况下,规范或标准限制了您的操作范围。我不确定在编程中是否会遇到许多由于规范不能满足所有要求而导致偏离或扩展规范的实现。

有时候使用实现细节的人可能会有测试用例,尽管很难为有秩序的人提供可靠的测试用例。它最有可能是偶然获得成功,或者是很难可靠地产生行为。

如果您确实依赖于特定的实现,则必须对此进行记录。如果您的项目需要可移植性(代码可以在您的控制之外的其他人的设置上运行,并且您希望获得最大的兼容性),那么在这种情况下,依靠特定的实现(例如按键顺序)不是一个好主意。

在您完全控制要使用的实现的情况下,完全取决于您使用哪种实现细节,同时请记住,由于普遍需要或期望升级实现,可能会被迫适应可移植性。

在这种情况下,最好的文档形式是内联,即在代码本身中,通常是为了使您至少易于识别要更改的区域(如果您从实现保证顺序切换为不这样做的话)。

您可以调整自己喜欢的格式,但是可以像...

/** @portability: insertion_ordered_keys */
for(let key in object) console.log();

您甚至可以将这种情况用代码包装起来:

forEachKeyInOrderOfInsertion(object, console.log)

再次,可能不太冗长,但足以识别依赖于此的案例。

对于您的实现能够保证键顺序的地方,您只需将其转换为原始顺序即可。

您可以将JS函数用于平台检测,诸如CPP,转译等模板处理。您可能还希望包装对象创建过程,并对跨边界的对象非常小心。如果某些东西在到达您之前就失去了顺序(例如,通过网络从客户端进行输入的JSON解码),那么您可能无法解决仅靠库访问的问题,甚至可能有人在调用您的库。 / p>

尽管您可能不需要这些,但可以在某些情况下进行一些可能会在以后破坏的事情,并记录下潜在的存在。

一个明显的例外是,如果实现保证一致性。在那种情况下,如果这不是真正的可变性,并且已经通过实现进行了记录,那么您可能会浪费时间装饰所有内容。该实现通常是 规范或有其自己的规范,您可以选择遵循该规范,而不是更笼统的规范。

在每种情况下,您最终都需要做出判断,您也可以选择冒险。只要您充分意识到潜在的问题,包括浪费时间避免自己不一定真正会遇到的问题,那就是您了解所有风险并考虑了您的情况,然后由您决定如何做。视情况而定,没有“应该”或“不应”。

如果您要使node.js公共库或要广泛分布的库超出控件的范围,那么我想依靠实现细节是不好的。相反,至少在发行说明中有免责声明,该库仅适合您的堆栈,如果人们想将其用于其他人,则可以对其进行修复并提出拉取请求。否则,如果没有记录,则应将其修复。