模板字符串作为对象属性名称
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`]: val
或 var 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;
但是为什么要麻烦呢?
【讨论】:
以上是关于模板字符串作为对象属性名称的主要内容,如果未能解决你的问题,请参考以下文章