First of all I assume you are talking about automatic conversion of primitive values to objects. This happens in two cases in JavaScript:
- When you pass a primitive value as the
this
value to .call
or .apply
(not in strict mode though).
- When you are trying to access a "property" of a primitive value, e.g.
"foo bar".split()
.
In the first case the conversion is permanent, i.e. this
will indeed reference an object, in the second the conversion only takes place internally for the duration of the evaluation
If you are not interested in the details of the conversion, you can ignore the rest of the answer.
1. Primitive value as this
When a function is exectued and its this
value is not an object, it is converted to one, at least in non-strict mode. This is described in §10.4.3 Entering Function Code [spec] in the ECMAScript 5.1 documentation:
The following steps are performed when control enters the execution context for function code contained in function object F
, a caller provided thisArg
, and a caller provided argumentsList
:
- If the function code is strict code, set the
ThisBinding
to thisArg
.
- Else if
thisArg
is null
or undefined
, set the ThisBinding
to the global object.
- Else if
Type(thisArg)
is not Object
, set the ThisBinding
to ToObject(thisArg
).
[...]
As you can see in step three the value is converted to an object by calling ToObject
[spec].
2. Property access
Something similar happens when you are trying to access properties (§11.2.1 Property Accessors [spec]). The quoted part here explains how the expression foo[bar]
is evaluated, i.e. how property access with the bracket notation is evaluated. The part we are interested in applies to dot notation as well.
The production MemberExpression : MemberExpression [ Expression ]
is evaluated as follows:
- Let
baseReference
be the result of evaluating MemberExpression
.
- Let
baseValue
be GetValue(baseReference)
.
[...]
8. Return a value of type Reference
whose base
value is baseValue
and whose referenced name is propertyNameString
, and whose strict
mode flag is strict
.
The important step is the last one: No matter to what MemberExpression
evaluates, it is converted to a value of type Reference
[spec]. This is a datatype only used in the specification and contains additional information about how the actual value should be retrieved from the reference (not to be confused with object references in actual JavaScript code!).
To get the "real" value/result from such a reference, the internal function GetValue(V)
(§8.7.1) [spec] is called (just like in step 2 in the above algorithm), where it says:
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)
.
[...]
Example:
Assume we have the expression
var foo = "BAR".toLowerCase();
This is an assignment expression which is evaluated as follows:
The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression
is evaluated as follows:
- Let
lref
be the result of evaluating LeftHandSideExpression
.
- Let
rref
be the result of evaluating AssignmentExpression
.
- Let
rval
be GetValue(rref)
.
[...]
Step 1: The left hand side is evaluated, which is the identifier foo
. How exactly identifiers are resolved is not important for this.
Step 2: The right hand side is evaluated, i.e. "BAR".toLowerCase()
. The internal result of that evaluation will be a reference value, similar to:
REFERENCE = {
base: "BAR",
propertyNameString: "toLowerCase",
strict: false
}
and stored in rref
.
Step 3: GetValue(rref)
is called. The base
of the reference is the value "BAR"
. Since this is a primitive value, ToObject
will be called to convert it to a temporary String
object. Furthermore, the reference is actually a property access, so GetValue
will eventually call the method toLowerCase
on the String
object and return the method's result.