0 tl;dr
1 问题来源
手写promise的时候突然被惊醒:promise凭什么能用catch做函数名啊?
不是说好变量名只能用非保留字,并且不以数字开头吗?
2 追问
于是直接百度。结果是明确的,当然百度不到。于是上谷歌用英文搜,果然早就有人在StackOverflow问了。不过提问者的出发点和我不同。
提问者想问的是:保留字作为对象属性名要不要加引号。
我想问的是:凭什么不用加引号保留字就可以作为属性名。因为我也知道,只要是字符串,无论什么内容都能做属性名。
算是殊途同归,卧龙凤雏吧。
3 解惑
上面的链接里说得非常详细。
简而言之,es5之前,确实是不能直接将保留字用作属性名的。一定要用只能用字符串配合中括号语法。
而es5之后,这个限制悄悄变了。
3.1 变量名的集合
ES的BNF把符号名划分成了几种集合:IdentifierName
,ReservedName
以及Identifier
。
其中Identifier
和ReservedName
没有交集,可以看作两者之间非此即彼,或者说互为补集。
ReservedName
就包含了关键字、未来保留字、null、true和false。此外的合法变量名通通可以看作是Identifier
的元素。
而ReservedName
以及Identifier
都是IdentifierName
的真子集。
3.2 对象字面量属性名的取值集合
ES5.1说明书中,对于一个对象字面量,属性名集合PropertyName
定义了其取值范围:IdentifierName
、StringLiteral
以及NumericLiteral
。
带恶人找到了:IdentifierName
。也就是说,ReservedName
和Identifier
都可以用作对象的属性名。
而在ES3的说明书中,这个地方只能使用Identifier
、StringLiteral
以及NumericLiteral
。不能使用ReservedName
。
4 总结
要不是脑袋搭错线我也不会想到这个问题,实在是太细了。
但是从另一个角度来看,其实我习以为常的定义并不能视作是毋庸置疑的结论,实际上问题往往就出在未经验证的先验知识上。