как я могу использовать переменную в качестве ключа в хэше в CoffeeScript?

#coffeescript #hashmap #literals

#coffeescript #хэш — карта #литералы

Вопрос:

например:

wtf

Итак:

 foo = "asdf"
{foo: "bar"}
eval foo

# how do I get {"asdf": "bar"} ?

# this will throw parse error:
{(eval foo): "bar"}
  

Это простой синтаксический вопрос: как мне заставить CoffeeScript создавать хэш динамически, а не делать это вручную?

Комментарии:

1. Для ясности, {(eval(foo)): "bar"} недопустимый JavaScript; синтаксис объектного литерала допускает только литеральные строки в качестве ключей. Для поддержки динамических ключей CoffeeScript должен был бы преобразовать этот код во что-то вроде __obj = {}; __obj[eval(foo)] = "bar"; .

Ответ №1:

Для всех, кто найдет этот вопрос в будущем, начиная с CoffeeScript 1.9.1, поддерживаются интерполированные объектные литеральные ключи!

Синтаксис выглядит следующим образом:

 myObject =
  a: 1
  "#{ 1   2 }": 3
  

См . https://github.com/jashkenas/coffeescript/commit/76c076db555c9ac7c325c3b285cd74644a9bf0d2

Комментарии:

1. Это ответ. Спасибо!

2. @KonstantinSchubert Да, это частный случай интерполяции строк. См . coffeescript.org/#strings

3. @bcherny Ах, спасибо! Я не знал, что для интерполяции строк требуются двойные кавычки.

4. Я не думаю, что вам даже нужны кавычки. [ 1 2 ]: 3 также будет работать.

Ответ №2:

Зачем вы eval вообще используете? Вы можете сделать это точно так же, как и в JavaScript:

 foo    = 'asdf'
h      = { }
h[foo] = 'bar'
  

Это переводится в этот JavaScript:

 var foo, h;
foo = 'asdf';
h = {};
h[foo] = 'bar';
  

И результат h выглядит так {'asdf': 'bar'} .

Комментарии:

1. 1. Я действительно обнаружил, что расширяю свои прототипы, чтобы включить универсальную функцию, подобную getByKey той, которая делает это для меня, когда мне нужно делать это часто.

Ответ №3:

CoffeeScript, как и JavaScript, не позволяет использовать выражения / переменные в качестве ключей в объектных литералах. Это ненадолго поддерживалось, но было удалено в версии 0.9.6. Вам нужно установить свойство после создания объекта.

 foo = 'asdf'

x = {}
x[foo] = 'bar'
alert x.asdf # Displays 'bar'
  

Ответ №4:

Несколько уродливый, но, тем не менее, однострочный (извините за опоздание):

{ "#{foo}": bar }

Комментарии:

1. В зависимости от вашей версии coffeescript это может быть невозможно.

Ответ №5:

Если вы хотите использовать минимальный синтаксис Coffeescript для определения ассоциативного массива, я предлагаю создать простой двухстрочный метод для преобразования variable name ключей в значения переменных после определения массива.

Вот как я это делаю (реальный массив намного больше):

 @sampleEvents = 
   session_started:
          K_TYPE: 'session_started'
          K_ACTIVITY_ID: 'activity'

   session_ended:
          K_TYPE: 'session_ended'

   question_answered:
          K_TYPE: 'question_answered'
          K_QUESTION: '1   3 = '
          K_STUDENT_A: '3'
          K_CORRECT_A: '4' #optional
          K_CORRECTNESS: 1 #optional
          K_SECONDS: 10 #optional
          K_DIFFICULTY: 4 #optional


for k, event of @sampleEvents
    for key, value of event
        delete event[key]
        event[eval(key.toString())] = value
  

SampleEvents Массив теперь:

 { session_started: 
   { t: 'session_started',
     aid: 'activity',
     time: 1347777946.554,
     sid: 1 },
  session_ended: 
   { t: 'session_ended', 
     time: 1347777946.554, 
     sid: 1 },
  question_answered: 
   { t: 'question_answered',
     q: '1   3 = ',
     sa: '3',
     ca: '4',
     c: 1,
     sec: 10,
     d: 4,
     time: 1347777946.554,
     sid: 1 },
  

Комментарии:

1. Зачем вам нужно eval в последней строке?

Ответ №6:

Попробуйте это:

 foo = "asdf"

eval "var x = {#{foo}: 'bar'}"
alert(x.asdf)
  

Комментарии:

1. это довольно умно, но плохая идея с точки зрения безопасности / производительности / наилучшей практики