0

我正在尝试扩展以下结构的对象(在 Coffeescript 中使用 JQuery):

objectThatIsAList = {
  'List Item'      : 
    callback       :=>
      return "Some value"
  'Another item'   :
    callback       :=>
      return "Another value"
  'The final item' :
    callback       :=>
      no
}

此对象用作大型基于咖啡脚本的框架中的下拉菜单的(动态)模型。

我正在扩展它

objectThatIsAList = $.extend {}, objectThatIsAList,  {
  'New Item' :
    callback :=>
      return "New stuff"
}

这会产生这样的对象(添加注释以显示预期结果)

objectThatIsAList = {
  'List Item'      : 
    callback       :=>
      return "Some value"
  'Another item'   :
    callback       :=>
      return "Another value"

  # this should be last
  'The final item' :
    callback       :=>
      no

  # this should not be last
  'New Item'       :
    callback       :=>
      return "New stuff"
}

显然,对象得到了正确扩展,但是属性的顺序与构建列表的目的相关。我更希望'Final Item'作为扩展对象的第四个而不是第三个属性

但我的研究并未显示对该$.extend方法的索引支持。是否有人成功实现了这样的功能和/或有提示如何将对象属性“插入”到某个位置的另一个对象中?

还是有一种聪明的方法可以在$.extend?

不一定非得是 Coffee,即使是 JS 或 Pseudocode 也会有很大帮助。

编辑:

这是我提出的解决方案,它扩展了遗留代码以获取数组并将它们转换为对象(在整个框架中被广泛使用,并且更改原始代码会破坏很多工作代码):

# this comparison yields a data object that is passed to a method rendering a menu
if o.menu instanceof Array
  menuArrayToObj = {}
  for menuObject in o.menu
    for menuObjectProperty,menuObjectValue of menuObject
      menuArrayToObj[menuObjectProperty]=menuObjectValue if menuObjectProperty? and menuObjectValue?
  o.menu = menuArrayToObj
else o.menu 

有了这个,它可以被提供一个对象或一个数组。后者很容易通过接头插入。

4

3 回答 3

2

Javascript 对象根据定义是无序的

如果你想保持一个顺序,你需要一个Array代替。

一个很好的例子是 jQueryUI 对话框对象。尽管可以Object按照您对buttons选项的方式使用 an ,但如果您要求各个按钮按特定顺序排列,则必须提供对象数组

使用此模型,您的对象将如下所示:

arrayThatIsAList = [
  { title: 'List Item', callback: ... },
  { title: 'Another Item', callback: ... },
  { title: 'New Item', callback: ... },
  { title: 'The final item', callback: ... }
];
于 2012-10-16T23:02:01.733 回答
1

$.extend()用于将 2 个或多个对象合并为一个。它不管理订单

如果你想对数据进行排序,你应该使用一个对象数组(它允许你用它的索引来操作数据)并使用一个自定义排序函数来比较你的对象标题:

yourArray.sort(sortfunction);

function sortfunction(yourObjectA, yourObjectB){
    //Compare yourObjectA and yourObjectB, and return -1, 0, or 1
}
于 2012-10-16T23:25:24.313 回答
0

将具有第一个属性的对象作为调用的第一个参数$.extend

objectThatIsAList = $.extend { 
  'New Item' : 
    callback :=> 
      return "New stuff" 
}, objectThatIsAList

“不!” ,你喊道,“ECMAScript 规范明确地未定义属性枚举排序!”

是的,没错。有效点。 但是,所有现代 ECMAScript 实现都按照定义的顺序枚举属性。它成为事实上的标准。在这里试试:jsfiddle.net/TqfNE。我怀疑任何人都可以找到按定义顺序以外的顺序列出属性的浏览器。

因此,不能保证符合规范,但出于所有实际目的,它可以始终如一地工作。

但是请注意,如果您开始使用整数作为属性名称,您在浏览器之间得到不一致的结果。

于 2012-10-16T23:10:45.443 回答