[英]Why are methods of String.prototype available to string literals?
This question has come out of another , which concerns the behaviour of console.dir
with string literals. 这个问题来自另一个问题 ,它涉及使用字符串文字的
console.dir
的行为。 In particular, see the comments on my answer . 特别是,请参阅我的回答评论。
As we all know, String
objects in JavaScript have a number of methods. 众所周知,JavaScript中的
String
对象有许多方法。 Those methods are defined on the String.prototype
object. 这些方法在
String.prototype
对象上定义。 String.prototype.toUpperCase
for example. 例如
String.prototype.toUpperCase
。 We can therefore do things like this: 因此我们可以这样做:
var s = new String("hello"),
s2 = s.toUpperCase(); //toUpperCase is a method on String.prototype
However, we can also do this: 但是,我们也可以这样做:
var s = "hello", //s is a string literal, not an instance of String
s2 = s.toUpperCase();
Clearly, the JavaScript interpreter is doing some form of conversion/cast when you call a method of String.prototype
on a string literal. 很明显,当您在字符串文字上调用
String.prototype
的方法时,JavaScript解释器正在进行某种形式的转换/转换。 However, I can't find any reference to this in the spec . 但是,我在规范中找不到任何对此的引用。
It makes sense, because otherwise you'd have to explicity cast every string literal to a String
object before you could use any of the methods, and that would be quite annoying. 这是有道理的,因为否则你必须明确地将每个字符串文字强制转换为
String
对象,然后才能使用任何方法,这将非常烦人。
So my question is, where is this functionality described, and am I right in assuming the literal value is temporarily cast to an instance of String
? 所以我的问题是,这个功能在哪里描述,我是否正确假设文字值暂时转换为
String
的实例? Am I over-thinking this and missing something obvious? 我是否过度思考并忽略了一些明显的东西?
It's defined here: 它在这里定义:
The following [[Get]] internal method is used by GetValue when V is a property reference with a primitive base value.
当V是具有基本基值的属性引用时,GetValue使用以下[[Get]]内部方法。 It is called using base as its this value and with property P as its argument.
使用base作为其值并使用属性P作为其参数调用它。 The following steps are taken:
采取以下步骤:
- Let O be ToObject(base).
设O为ToObject(base)。
- Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.
设desc是调用属性名为P的O的[[GetProperty]]内部方法的结果。
- If desc is undefined, return undefined.
如果未定义desc,则返回undefined。
- If IsDataDescriptor(desc) is true, return desc.[[Value]].
如果IsDataDescriptor(desc)为true,则返回desc。[[Value]]。
- Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be desc.[[Get]].
否则,IsAccessorDescriptor(desc)必须为true,所以让getter为desc。[[Get]]。
- If getter is undefined, return undefined.
如果未定义getter,则返回undefined。
- Return the result calling the [[Call]] internal method of getter providing base as the this value and providing no arguments.
返回调用getter提供base的[[Call]]内部方法的结果作为此值并且不提供参数。
NOTE The object that may be created in step 1 is not accessible outside of the above method.
注意在上述方法之外无法访问可能在步骤1中创建的对象。 An implementation might choose to avoid the actual creation of the object.
实现可能会选择避免实际创建对象。 The only situation where such an actual property access that uses this internal method can have visible effect is when it invokes an accessor function.
使用此内部方法的此类实际属性访问可以具有可见效果的唯一情况是它调用访问器函数时。
Source: http://es5.github.com/#x8.7.1 资料来源: http : //es5.github.com/#x8.7.1
The primitive string value is coerced to an object in step 1. 在步骤1中将原始字符串值强制转换为对象。
Example 1 例1
var str = 'some string';
str = str.toUpperCase();
Here, the expression str.toUpperCase
is evaluated according to the semantics defined in 11.2.1 Property Accessors : 这里,表达式
str.toUpperCase
是根据11.2.1属性访问器中定义的语义计算的:
str
is evaluated according to identifier resolution (see 10.2.2.1 GetIdentifierReference ). str
根据标识符解析进行评估(参见10.2.2.1 GetIdentifierReference )。 The result is a reference whose base value is the environment record of the current lexical environment, and whose referenced name is "str"
. "str"
。 This reference is the baseReference . GetValue(baseReference)
. GetValue(baseReference)
确定的。 Since baseReference is not a property reference (its base value is not an object or a primitive value, but an environment record), the GetBindingValue()
method is called in order to retrieve the value of the reference. GetBindingValue()
方法以检索引用的值。 This method returns the value of the local variable str
, ie the primitive String value 'some string'
. str
的值,即原始String值'some string'
。 This value is the baseValue . 'toUpperCase'
. 'toUpperCase'
。 (I've shortened this process a bit for the sake of simplicity.) So, there are two references involved in this process: 因此,此过程涉及两个引用:
str
(base value: the environment record, referenced name: 'str'
) str
(基值:环境记录,引用名称: 'str'
) str.toUpperCase
(base value: 'some string'
, referenced name: 'toUpperCase'
) str.toUpperCase
(基值: 'some string'
,引用名称: 'toUpperCase'
) Finally, the invocation operator ()
is executed on the latter reference. 最后,调用operator
()
在后一个引用上执行。 The value of that reference is determined according to the semantics defined at the top of this answer. 该引用的值是根据本答案顶部定义的语义确定的。
Example 2 例2
var str = 'some string'.toUpperCase();
Here, the expression 'some string'.toUpperCase
is evaluated according to the same "Property Accessor" semantics as in example 1: 这里,表达式
'some string'.toUpperCase
是根据与示例1中相同的“Property Accessor”语义计算的:
'some string'
obviously evaluates to the primitive String value 'some string'
. 'some string'
显然计算为原始字符串值'some string'
。 This is the baseReference . GetValue(baseReference)
. GetValue(baseReference)
确定的。 Since baseReference is not a reference, the method simply returns the argument value, ie baseValue = baseReference . As you can see, just like in example 1, baseValue is the primitive String value 'some string'
. 如您所见,就像在示例1中一样, baseValue是原始String值
'some string'
。 The steps 3 and 4 are equivalent to the steps 3 and 4 in example 1. 步骤3和4等同于示例1中的步骤3和4。
So, both the identifier reference str
and the string literal 'some string'
evaluate to the same value - the primitive String value 'some string'
- and that value is used as the baseValue for the new reference which is then invoked with ()
. 因此,标识符引用
str
和字符串文字'some string'
计算为相同的值 - 原始字符串值'some string'
- 该值用作新引用的baseValue ,然后用()
调用。 And since this reference has a primitive base value, the semantics defined at the beginning of my answer apply. 由于此引用具有原始基值,因此在我的答案开头定义的语义适用。
That's exactly what it's doing. 这正是它正在做的事情。
Javascript boxes
primitive types as needed. JavaScript的
boxes
需要原始类型。
Here's some more information: 以下是一些更多信息:
http://princepthomas.blogspot.com/2011/07/auto-boxing-javascript-primitive-types.html http://princepthomas.blogspot.com/2011/07/auto-boxing-javascript-primitive-types.html
Per the reference literals are converted to objects: 根据参考文字转换为对象:
String literals (denoted by double or single quotes) and strings returned from String calls in a non-constructor context (ie, without using the new keyword) are primitive strings.
字符串文字(用双引号或单引号表示)和从非构造函数上下文中的String调用返回的字符串(即,不使用new关键字)是原始字符串。 JavaScript automatically converts primitives and String objects, so that it's possible to use String object methods for primitive strings.
JavaScript自动转换基元和String对象,因此可以对原始字符串使用String对象方法。
You are almost right. 你几乎是对的。 There is something called autoboxing (wrapping primitives in objects) http://princepthomas.blogspot.com/2011/07/auto-boxing-javascript-primitive-types.html
有一种叫做autoboxing(在对象中包装原语) http://princepthomas.blogspot.com/2011/07/auto-boxing-javascript-primitive-types.html
edit: sory for duplication of Mike Christensen link - I did not notice it. 编辑:索里重复迈克克里斯滕森链接 - 我没有注意到它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.