模板字符串作为对象属性名

为什么 JavaScript 不允许模板字符串作为对象属性键? 例如,当我输入:

foo = {`bar`: 'baz'}

在 NodeJS REPL 中,它抛出一个 SyntaxError,其中包含一个带有长堆栈跟踪的“意外模板字符串”。但是,属性值没有问题,这并不意外。类似的错误发生在浏览器中,例如,Firebug 抛出一个带有“无效属性 id”的 SyntaxError

在“计算属性名称”中允许使用模板字符串。例如,在所有支持这种语法的浏览器中,这种方法都能很好地编译:

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

并创建对象 {"bar1": "baz"}

为什么不允许模板字符串作为文字对象键?是因为性能原因吗?必须编译模板字符串,可能在运行时(如果我错了请纠正我) ,这意味着每次它遇到这个对象,解释器将不得不计算对象名称。尽管从 ES5开始我们就有了 getter 和 setter,但是考虑到像“熟”模板字符串这样的因素,这似乎会变得很慢。Firefox 没有提到这是一个错误,这就是为什么我发现它是意想不到的。这种语法将来会被允许吗?

50011 次浏览

Why are template strings not allowed as literal object keys?

Template strings are expressions, not literals1. You can only use string literals (and identifiers) for property names, for everything else - that is not known to be static - you need a computed property name.

Is it for performance reasons?

No, that's unlikely. It's to ease parsing, and makes it easy to distinguish constant (statically known) property names from dynamically computed ones.

And mostly, it's a feature that no one needs. It doesn't simplify or shorten anything, and what you would achieve with it is already possible.

Will the syntax be allowed sometime in the future?

Nope.

1: Even when they're called "template literals", technically they aren't literals. And: templates don't even need to be strings, they can evaluate to anything.

Object keys are expected to be Strings:

let obj1 = { name: "Alex", age: "28"} // this is a 'normal' style

If the expression provided as a key is not a string, the engine will attempt to Coerse it into a string.

let obj2 = { 5: "Banana", 10: "Apple" } // e.g. number key is coersed into string

Template Strings need to be evaluated first. Therefore are not 'coersible'. Hense, the engine throws an error, because it tries to coerse them (example 1)

Arrays, on the other hand, are naturally coersible to string, therefore can be used as completely legal keys

Moreover, arrays that contain template strings may be used as perfectly legal keys when creating an object, because the engine first evaluates the template expression, then coerses the array into a string (example 2)

see examples:

    /* example 1 */ {`foo`: "bar"}   // Error: template strs aren't coersible

To be able to use a template string as an object key, just wrap it as single element of an array:

    /* example 2 */ {[`foo`]: "bar"} /* OK: {foo: "bar"}, the internal `foo`
template is first resolved to a native
"foo" string, resulting in array ["foo"],
which then coersed to the "foo" key.*/
    

/* example 3 */ const obj = {foo: "bar"}
const obj1 = {[obj.foo]: "bar"} // OK: {bar: "bar"} !!

I'm posting this answer to lift @Bergi's very upvoted comment to an answer. If you want to use a dynamic value from a variable as your object key in your object literal, just use a computed property:

const dynamicKey = someCondition ? 'someKeyName' : 'otherKeyName';
const obj = {[dynamicKey]: val};

You could also write that as:

const obj = {[`${dynamicKey}`]: val};

but why bother?