Итерации по объектам JavaScript с помощью руля - PullRequest
3 голосов
/ 01 февраля 2012

Я пытаюсь зарегистрировать помощников в Handlebars, чтобы разрешить перебирать объекты JSON. Эта суть выглядела как подходящее решение.Я преобразовал это в следующий CoffeeScript.Кажется, ничего не происходит, когда я использую один из помощников (это справедливо как для ванильного 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}}

В настоящее время я использую gem 'handlebars-assets' в Gemfile для добавления рулей в приложение rails.

1 Ответ

7 голосов
/ 02 февраля 2012

Ваша транслитерация 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/

...