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

Posted

技术标签:

【中文标题】模板字符串作为对象属性名称【英文标题】:Template String As Object Property Name 【发布时间】:2016-01-16 14:28:32 【问题描述】:

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

foo = `bar`: 'baz'

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

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

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

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

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

【问题讨论】:

不是这个原因,引入了计算属性名。是的,您需要在它周围加上大括号,但它在语法上似乎也更适合作为解决各种场景的通用解决方案。 我只是在重新考虑我的答案,并不太确定它是否正确。现在我正在研究 ES6 文档.... 为什么不允许模板字符串作为文字对象键? 他们是,你只是语法错误......? 【参考方案1】:

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

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

是出于性能原因吗?

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

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

将来某个时候会允许这种语法吗?

没有。

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

【讨论】:

`var obj = `$dyanmicKey` : val ` 呢? @b4d4r:不——你需要使用计算属性。 var obj = [`$dyanmicKey`]: valvar obj = [dyanmicKey]: val 伙计,为什么不呢。他们只是不希望人们在里面放表情哈...... @Bergi 如何解决以下问题:profile.preferences.networks[$network.name] @SafalPillai 不在未加引号的标识符名称中,但 "#key": "value" 完全没问题。【参考方案2】:

对象键应该是字符串。

如果作为键提供的表达式不是字符串,引擎将尝试将其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" !!

【讨论】:

令人着迷。我从来没有想过为什么数组可以用作对象键名,但现在它非常有意义!【参考方案3】:

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

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

你也可以这样写:

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

但是为什么要麻烦呢?

【讨论】:

以上是关于模板字符串作为对象属性名称的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript对象:按名称作为字符串访问变量属性[重复]

通过对象的名称作为字符串 c# 访问对象

Django 表单名称作为 HTML 模板中的属性

在对象上调用以字符串作为名称的方法

js对象属性的命名规则

从字符串声明属性名称[重复]