为什么String.prototype的方法可用于字符串文字?
这个问题已经出来了another,其中涉及console.dir
与字符串文字的行为。尤其请参阅my answer的评论。为什么String.prototype的方法可用于字符串文字?
众所周知,String
JavaScript中的对象有许多方法。这些方法在String.prototype
对象上定义。例如,String.prototype.toUpperCase
。因此,我们可以做这样的事情:
var s = new String("hello"),
s2 = s.toUpperCase(); //toUpperCase is a method on String.prototype
但是,我们也可以这样做:
var s = "hello", //s is a string literal, not an instance of String
s2 = s.toUpperCase();
显然,JavaScript解释正在做某种形式的转换/施放的,当你调用String.prototype
的方法在字符串文字上。但是,我在spec中找不到任何对此的提及。
它是有道理的,因为否则,在使用任何方法之前,您必须明确地将每个字符串文字转换为String
对象,并且这会很烦人。
所以我的问题是,这个功能描述在哪里,我是否正确地假设文字值暂时被转换为String
的实例?我是否过度思考这一点,并忽略了一些明显的东西
它定义这里:
以下[[获取]]内部方法用于在getValue当V是与图元碱值的 属性参考。它被称为使用 基地作为它的这个值并且以属性P作为它的参数。采取以下步骤 :
- 设O为ToObject(base)。
- 设desc为调用属性名称为P的[[GetProperty]]的内部方法的结果。
- 如果desc未定义,则返回undefined。
- 如果IsDataDescriptor(desc)为true,则返回desc。[[Value]]。
- 否则,IsAccessorDescriptor(desc)必须为真,因此,让getter被描述为[[Get]]。
- 如果getter未定义,则返回undefined。
- 返回调用getter提供库的[[Call]]内部方法的结果作为该值并且不提供参数。
注意在上述方法之外,可能在步骤1中创建的对象不可访问 。实现可能会选择避免实际创建对象。使用此内部方法的这种实际属性访问唯一可见的 效果是当它调用访问器函数时。
来源:http://es5.github.com/#x8.7.1
的原始字符串值被强制转换到对象在步骤1
实施例1
var str = 'some string';
str = str.toUpperCase();
这里,表述str.toUpperCase
是根据在11.2.1 Property Accessors定义的语义进行评估:
- 标识符
str
根据标识符解析(见10.2.2.1 GetIdentifierReference)来评价。结果是一个引用,其基值是当前词汇环境的环境记录,其引用名称为"str"
。该参考文献是baseReference。 -
baseValue通过执行
GetValue(baseReference)
来确定。由于baseReference不是属性引用(其基本值不是对象或原始值,而是环境记录),因此将调用GetBindingValue()
方法以检索引用的值。该方法返回局部变量str
的值,即基元字符串值'some string'
。该值是baseValue。 -
propertyNameValue求值为原始字符串值
'toUpperCase'
。 (为简单起见,我略微缩短了此过程。) - 创建一个新的引用,其基值为baseValue,其引用的名称为propertyNameValue。
因此,有参与这一进程的两个引用:
-
str
(基值:环境记录,引用名称:'str'
) -
str.toUpperCase
(基值:'some string'
,引用的名字:'toUpperCase'
)
最后,调用运算符()
在后面的引用上执行。该引用的值根据此答案顶部定义的语义确定。
实施例2
var str = 'some string'.toUpperCase();
这里,表述'some string'.toUpperCase
根据相同的 “属性访问” 的语义被评估如实施例1:
- 的字符串文字
'some string'
明显计算结果为原始字符串值'some string'
。这是baseReference。 (不要让名称让你感到困惑 - 这是一个字符串值,不是参考。) -
baseValue通过执行
GetValue(baseReference)
来确定。由于baseReference不是参考,所以该方法简单地返回参数值,即baseValue = baseReference。
正如你所看到的,就像例1中,baseValue是原始字符串值'some string'
。步骤3和4是等价于实例中的步骤3和4 1.
所以,两者的标识参考str
和字符串文字'some string'
评价为相同的值 - 的原始字符串值'some string'
- 并使用该值作为baseValue为新的参考,然后用()
调用。由于这个引用有一个基本的基本值,所以在我的答案的开头定义的语义适用。
啊哈!非常感谢你:) – 2011-12-20 21:12:50
我也读过,但如何与参考相关的字符串文字?什么是引用,或者更确切地说,什么是已解析的名称绑定? – 2011-12-20 21:15:05
'+ 1' - 我在找那个! – 2011-12-20 21:16:10
这正是它在做什么。
Javascript boxes
根据需要使用原始类型。
这里的一些信息:
http://princepthomas.blogspot.com/2011/07/auto-boxing-javascript-primitive-types.html
就像我所假设的那样,但我仍然无法在ECMAScript规范中找到它。你知道这个行为在那里描述吗? – 2011-12-20 21:09:04
每the reference文字转换为对象:
字符串(双或单引号表示)和字符串 返回从字符串中调用非构造函数上下文(即没有使用新关键字的 )是原始字符串。 JavaScript自动地将 转换为基本字符串和字符串对象,因此可以使用 字符串对象方法来处理基本字符串。
这就如我所设想的那样,但我仍然无法在ECMAScript规范中找到它。你知道这个行为在那里描述吗? – 2011-12-20 21:06:05
你几乎是对的。有一种叫做自动装箱(在包装的对象基本类型)http://princepthomas.blogspot.com/2011/07/auto-boxing-javascript-primitive-types.html
编辑:索里迈克克里斯滕森链接复制 - 我没有注意到它。
顺便说一句'新的字符串(值)'表示法是100%无用的...不要使用它。 – 2011-12-20 21:00:20
我知道是。问题是为什么。规范中描述了哪些内容? – 2011-12-20 21:00:56
字符串文字是一个字符串对象:'typeof“hello”===“string”'返回true。这是否解决了这个问题? – bbg 2011-12-20 21:01:35