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

Template String As Object Property Name

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

foo = {`bar`: 'baz'}

进入 NodeJS REPL,它抛出一个 SyntaxError 和 "Unexpected template string" 以及一个长堆栈跟踪。 属性 值很好,但这并不意外。类似的错误发生在浏览器中,例如,Firebug 抛出 SyntaxError with "invalid property id".

"computed property names" 中允许使用模板字符串。例如,这在所有支持语法的浏览器中编译得很好:

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

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

为什么模板字符串不允许作为文字对象键?是否出于性能原因?模板字符串必须编译,可能在运行时编译(如果我错了请纠正我),这意味着每次遇到这个对象时,解释器都必须计算对象名称。考虑到 "cooked" 模板字符串之类的因素,这似乎会变慢,尽管我们从 ES5 开始就有了 getter 和 setter。 Firefox 没有将此作为错误提及,这就是我发现它出乎意料的原因。将来某个时候会允许使用该语法吗?

Why are template strings not allowed as literal object keys?

模板字符串是表达式,而不是文字1。您只能对 属性 名称使用字符串文字(和标识符),对于其他所有内容 - 不知道是静态的 - 您需要一个计算的 属性 名称。

Is it for performance reasons?

不,这不太可能。这是为了简化解析,并且可以轻松区分常量(静态已知)属性 名称与动态计算的名称。

大多数情况下,这是一项没有人需要的功能。它不会简化或缩短任何内容,您可以用它实现的目标已经成为可能。

Will the syntax be allowed sometime in the future?

没有。

1:即使它们被称为 "template literals",从技术上讲它们也不是 literals。并且:模板甚至不需要是字符串,它们可以计算为任何东西。

对象键应该是字符串。

如果作为键提供的表达式不是字符串,引擎将尝试将其强制为字符串。

模板字符串不是 'coersible',因此,引擎会在尝试强制转换它们时抛出错误(示例 1)

另一方面,数组自然可转换为字符串,因此可以用作完全合法的键

此外,包含模板字符串的数组可以在创建对象时用作完全合法的键,因为引擎首先计算模板表达式,然后将数组强制转换为字符串(示例 2)

查看示例:

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

为了能够将模板字符串用作对象键,只需将其包装为数组的单个元素即可:

    /* 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"} !!

我发布此答案是为了提升@Bergi 对答案的非常赞成的评论。如果你想在你的对象文字中使用一个变量的动态值作为你的对象键,只需使用计算 属性:

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

你也可以这样写:

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

但何必呢?