#coffeescript #hashmap #literals
#coffeescript #хэш — карта #литералы
Вопрос:
например:
Итак:
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. это довольно умно, но плохая идея с точки зрения безопасности / производительности / наилучшей практики