Строка шаблона как имя свойства объекта

Почему JavaScript не позволяет использовать строку шаблона в качестве ключа свойства объекта? Например, когда я ввожу:

foo = {`bar`: 'baz'}

в NodeJS REPL он выдает SyntaxError с «Неожиданной строкой шаблона» с длинной трассировкой стека. Однако значения свойств в порядке, что не так уж неожиданно. Подобные ошибки случаются и в браузере, например, Firebug выдает SyntaxError с "недопустимым идентификатором свойства".

Строки шаблона разрешены в "вычисляемых именах свойств". Например, это прекрасно компилируется во всех браузерах, поддерживающих синтаксис:

var foo = {
    [`bar` + 1]: `baz`
};

и создает объект {"bar1": "baz"}.

Почему шаблонные строки нельзя использовать в качестве литеральных ключей объекта? Это связано с производительностью? Строки шаблона должны быть скомпилированы, возможно, во время выполнения (поправьте меня, если я ошибаюсь), что означает, что каждый раз, когда он сталкивается с этим объектом, интерпретатор должен будет вычислять имя объекта. Учитывая такие вещи, как «приготовленные» строки шаблона, кажется, что это может стать медленным, хотя у нас были геттеры и сеттеры начиная с ES5. Firefox не упоминает об этом как об ошибке, поэтому я нашел это неожиданным. Будет ли разрешен синтаксис когда-нибудь в будущем?


person trysis    schedule 18.10.2015    source источник
comment
Не по этой ли причине вводятся вычисляемые имена свойств. Да, вам нужны фигурные скобки вокруг него, но синтаксически он также кажется лучше в качестве общего решения для различных сценариев.   -  person Praveen Puglia    schedule 18.10.2015
comment
Я просто переосмысливаю свой ответ и не слишком уверен, что он был правильным. Теперь я копаюсь в документах ES6....   -  person Max    schedule 18.10.2015
comment
Почему шаблонные строки не разрешены в качестве литеральных ключей объектов? Да, у вас просто неправильный синтаксис...?   -  person Mathletics    schedule 09.03.2016


Ответы (2)


Почему строки шаблона не разрешены в качестве литеральных ключей объекта?

Строки шаблона — это выражения, а не литералы1. Вы можете использовать только строковые литералы (и идентификаторы) для имен свойств, для всего остального, что не является статическим, вам нужно вычисляемое имя свойства.

Это из соображений производительности?

Нет, это маловероятно. Это упрощает синтаксический анализ и позволяет легко отличить постоянные (статически известные) имена свойств от динамически вычисляемых.

И в основном это функция, которая никому не нужна. Он ничего не упрощает и не укорачивает, и то, чего вы с его помощью достигнете, уже возможно.

Будет ли разрешен синтаксис когда-нибудь в будущем?

Неа.

1: Даже когда они называются "шаблонными литералами", технически они не являются литералы. И: шаблоны даже не обязательно должны быть строками, они могут вычисляться как угодно.

person Bergi    schedule 09.03.2016
comment
как насчет `var obj = {`${dyanmicKey}`: val } `? - person b4d4r; 31.05.2016
comment
@ b4d4r: Нет, вам нужно использовать вычисляемые свойства. Либо var obj = {[`${dyanmicKey}`]: val}, либо просто var obj = {[dyanmicKey]: val}. - person Bergi; 31.05.2016
comment
Мужик, а почему бы и нет. Они просто не хотят, чтобы люди вставляли туда выражения, ха... - person geoyws; 06.10.2016
comment
@Bergi Как можно исправить следующее: profile.preferences.networks[${network.name}] - person basickarl; 20.04.2017
comment
@KarlMorrison Просто бросить части ${ }? - person Bergi; 20.04.2017
comment
@Bergi Ах, черт, это убрало косые комментарии, посмотри еще раз здесь `profile.preferences.networks[${network.name}]` - person basickarl; 20.04.2017
comment
@KarlMorrison И какую проблему нужно решить с этим? - person Bergi; 20.04.2017
comment
Отлично @Bergi! Все попробуйте это: const k = 'key'; const о = {[k]:1}; console.log(о); - person Denis Truffaut; 25.06.2017
comment
В соответствующей заметке: разрешено ли # внутри ключевой строки? - person Safal Pillai; 12.06.2020
comment
@SafalPillai Не внутри имени идентификатора без кавычек, но {"#key": "value"} совершенно нормально. - person Bergi; 12.06.2020
comment
Что это значит: шаблоны даже не обязательно должны быть строками, они могут вычисляться как угодно - person adiga; 04.06.2021
comment
@adiga Теговый литерал шаблона оценивает любое значение, которое возвращает функция тега, например. регулярное выражение или абстрактное синтаксическое дерево или что-то еще. - person Bergi; 04.06.2021

Ожидается, что ключи объекта будут строками.

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

Строки шаблона не являются "приводимыми", следовательно, движок выдает ошибку, пытаясь их принудить...

Массивы, с другой стороны, естественным образом преобразуются в строки, поэтому их можно использовать как полностью допустимые ключи.

Более того, массивы, содержащие строки шаблона, могут использоваться как вполне законные ключи при создании объекта, потому что движок сначала оценивает выражение шаблона, а затем преобразует массив в строку, см. здесь:

{`foo`: "bar"} //Error
{[`foo`]: "bar"} // OK => {foo: "bar"}
const obj = {foo: "bar"}
const obj1 = {[obj.foo]: "bar"} // OK => {bar: "bar"} !!
person Nati Kamusher    schedule 27.05.2021
comment
Очаровательный. Я никогда не задумывался о том, почему массив работает как имя ключа объекта, но теперь это имеет смысл! - person trysis; 28.05.2021