Definitive JavaScript by David Flanagan makes a distinction between Objects and Primitives.
He defines the primitives as Number, String, Boolean, Null, and Undefined, as does the standard.
However, would it be more accurate to define a primitive, as subset of object, i.e. to call them Primitive Objects.
Because they have their own methods and are complex entities.
Actual Question
Would Primitive Object be more accurate than Object when defining String, Boolean, and Number?
Objects and primitives are distinct:
typeof 42 === "number"             
typeof new Number(42) === "object"
new Number(42) !== 42
However, when necessary, primitives are automatically wrapped by temporary objects, which can be automatically converted back into primitives:
(42).toString() === "42"
new Number(42) == 42
new Number(42) + 1 === 43
Especially in the context of the Java and C# programming languages, this sort of behavior is called autoboxing. As wrapper objects have some confusing characteristics, for example:
Boolean(new Boolean(false)) === true
it is good practice to avoid intentionally storing them in variables and instead use primitives whenever possible.
It's not about semantics, look:
var threePrimitive = 3;
var threeObject = new Number(3);
threePrimitive.toFixed(2); // 3.00
threeObject.toFixed(2); // 3.00
threePrimitive.foo = true
threeObject.foo = true;
threePrimitive.foo; // undefined
threeObject.foo; // true
Primitives are wrapped in objects when you try to call a method on them, but after initial use the object is thrown away.
As for how this is stated in the specification, I'm not 100% sure, but here is what I think (based on the tips left by Bergi in one of his answers. Section 11.2.1 states that the accessor properties should be evaluated as follows:
- Let baseReference be the result of evaluating MemberExpression.
- Let baseValue be
GetValue(baseReference).(...)
Then in 8.7.1 we see the following:
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
thisvalue 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.
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