使用把手迭代javascript对象

时间:2012-02-01 19:36:20

标签: javascript ruby-on-rails coffeescript handlebars.js

我正在尝试使用Handlebars注册帮助程序以允许迭代JSON对象。 This gist看起来像是一个合适的解决方案。我将其转换为以下CoffeeScript。当我使用任何一个帮助程序时,似乎没有任何事情发生(对于vanilla JavaScript和CoffeeScript版本都适用)。有什么想法吗?

$ ->
  Handlebars.registerHelper "key_value", (obj, fn)->
    buffer = ""
    key 
    for key in obj 
      if obj.hasOwnProperty(key)
        buffer += fn({key: key, value: obj[key]})
    buffer

  Handlebars.registerHelper "each_with_key", (obj, fn)->
    context
    buffer = ""
    key 
    keyName = fn.hash.key
    for key in obj 
      if obj.hasOwnProperty(key)
        context = obj[key]
        if keyName
          context[keyName] = key 
          buffer += fn(context)
    buffer

在模板中:

{{#key_value categories}}
I'M ALIVE!!
{{/key_value}}

{{#each_with_key categories key="category_id"}}
I'M ALIVE!!
{{/each_with_key}}

我目前在Gemfile中使用gem 'handlebars-assets'将把手添加到rails应用程序。

1 个答案:

答案 0 :(得分:7)

您的JavaScript到CoffeeScript音译被破坏了。您不使用for ... in在CoffeeScript中迭代对象,而是使用for k, v of ...

  

使用of来表示对对象属性的理解,而不是数组中的值。

这个CoffeeScript循环:

for x in y
    ...

成为这个JavaScript:

for (_i = 0, _len = y.length; _i < _len; _i++) {
  x = a[_i];
  ...
}

因此,如果y是没有length属性的对象,那么_len将为undefined,并且JavaScript for(;;)循环根本不会迭代

您还应该使用own代替hasOwnProperty

  

如果您只想迭代在对象本身上定义的键,通过添加hasOwnProperty检查以避免可能从原型中插入的属性,使用for own key, value of object

但这更方便而不是正确。

此外,CoffeeScript循环是表达式,因此您通常会说array = expr for own k, v in o或等效形式:

array = for own k, v in o
    expr

如果expr超过一行或太长而无法理解。

CoffeeScript中帮助者的正确且更惯用的版本看起来更像是这样:

Handlebars.registerHelper "key_value", (obj, fn)->
    (fn(key: key, value: value) for own key, value of obj).join('')

Handlebars.registerHelper "each_with_key", (obj, fn)->
    key_name = fn.hash.key
    buffer   = for own key, value of obj
        value[key_name] = key
        fn(value)
    buffer.join('')

演示:http://jsfiddle.net/ambiguous/LWTPv/