This question has come out of another, which concerns the behaviour of console.dir
with string literals. In particular, see the comments on my answer.
A
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 (i.e., without using the new keyword) are primitive strings. JavaScript automatically converts primitives and String objects, so that it's possible to use String object methods for primitive strings.
It's defined here:
The following [[Get]] internal method is used by GetValue when V is a property reference with a primitive base value. It is called using base as its this value and with property P as its argument. The following steps are taken:
- Let O be ToObject(base).
- Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.
- If desc is undefined, return undefined.
- If IsDataDescriptor(desc) is true, return desc.[[Value]].
- Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be desc.[[Get]].
- If getter is undefined, return undefined.
- Return the result calling the [[Call]] internal method of getter providing base as the this value and providing no arguments.
NOTE The object that may be created in step 1 is not accessible outside of the above method. 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
The primitive string value is coerced to an object in step 1.
Example 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
is evaluated according to identifier resolution (see 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"
. This reference is the baseReference.str
, i.e. the primitive String value 'some string'
. This value is the baseValue.'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.toUpperCase
(base value: 'some string'
, referenced name: 'toUpperCase'
)Finally, the invocation operator ()
is executed on the latter reference. The value of that reference is determined according to the semantics defined at the top of this answer.
Example 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'
obviously evaluates to the primitive String value 'some string'
. This is the baseReference. (Don't let the name confuse you - this is a string value, not a reference.)GetValue(baseReference)
. Since baseReference is not a reference, the method simply returns the argument value, i.e. baseValue = baseReference.As you can see, just like in example 1, baseValue is the primitive String value 'some string'
. The steps 3 and 4 are equivalent to the steps 3 and 4 in example 1.
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 ()
. 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.
Here's some more information:
http://princepthomas.blogspot.com/2011/07/auto-boxing-javascript-primitive-types.html
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
edit: sory for duplication of Mike Christensen link - I did not notice it.