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

IT技术 javascript node.js object-literal template-strings template-literals
2021-01-17 14:55:26

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

foo = {`bar`: 'baz'}

进入 NodeJS REPL,它会抛出一个SyntaxError带有“意外模板字符串”的带有长堆栈跟踪的字符串。然而,属性值很好,这并不出人意料。类似的错误发生在浏览器中,例如,Firebug 抛出一个SyntaxError“无效的属性 ID”。

“计算属性名称”中允许使用模板字符串。例如,这在支持语法的所有浏览器中都可以完美编译:

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

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

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

3个回答

为什么模板字符串不允许作为文字对象键?

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

是出于性能原因吗?

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

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

将来某个时候会允许使用该语法吗?

不。

1:即使它们被称为“模板文字”,从技术上讲,它们也不是文字并且:模板甚至不需要是字符串,它们可以评估任何东西。

@Bergi 如何解决以下问题: profile.preferences.networks[${network.name}]
2021-03-18 14:55:26
伙计,为什么不呢。他们只是不想让人在里面放表情啊……
2021-03-21 14:55:26
@SafalPillai 不在不带引号的标识符名称内,但{"#key": "value"}完全没问题。
2021-03-23 14:55:26
@b4d4r:不 - 您需要使用计算属性。无论是var obj = {[`${dyanmicKey}`]: val}或只是var obj = {[dyanmicKey]: val}
2021-04-02 14:55:26
` var obj = {`${dyanmicKey}` : val } ` 怎么样?
2021-04-07 14:55:26

对象键应该是字符串。

如果作为重点提供的表达式不是字符串,引擎将尝试Coerse它变成一个字符串。

模板字符串不是“可转换的”,因此,引擎在尝试转换它们时会抛出错误...

另一方面,数组自然可以转换为字符串,因此可以用作完全合法的键(示例 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"} !!
迷人。我从来没有想过为什么数组可以作为对象键名,但现在它完全有道理!
2021-04-07 14:55:26

我发布这个答案是为了提升@Bergi 对一个答案的高度评价。如果要使用变量中的动态值作为对象字面量中的对象键,只需使用计算属性:

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

你也可以这样写:

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

但为什么要打扰?