First of all I assume you are talking about automatic conversion of primitive values to objects. This happens in two cases in JavaScript:
this value to .call or .apply (not in strict mode though)."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 providedthisArg, and a caller providedargumentsList:
- If the function code is strict code, set the
ThisBindingtothisArg.- Else if
thisArgisnullorundefined, set theThisBindingto the global object.- Else if
Type(thisArg)is notObject, set theThisBindingtoToObject(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
baseReferencebe the result of evaluatingMemberExpression.- Let
baseValuebeGetValue(baseReference).
[...]8. Return a value of type
Referencewhosebasevalue isbaseValueand whose referenced name ispropertyNameString, and whosestrictmode flag isstrict.
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 byGetValuewhenVis a property reference with a primitive base value. It is called usingbaseas itsthisvalue and with propertyPas its argument. The following steps are taken:
- Let
ObeToObject(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 = AssignmentExpressionis evaluated as follows:
- Let
lrefbe the result of evaluatingLeftHandSideExpression.- Let
rrefbe the result of evaluatingAssignmentExpression.- Let
rvalbeGetValue(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.
Javascript boxes the this argument provided to call and apply in non-strict mode. From MDN:
if the method is a function in non-strict mode code,
nullandundefinedwill be replaced with the global object, and primitive values will be boxed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With