Does javascript autobox? - javascript

While working on another problem, I created this fiddle:
http://jsfiddle.net/tr2by/
function foo() {
// console.log(_.isBoolean(this));
console.log(this === true);
}
foo.call(true); // object:[object Boolean]
foo.apply(true); // object:[object Boolean]
Is this an example of auto-boxing?
Going from a value type to a reference type.
Here is a wikipedia def.

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.

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, null and undefined will be replaced with the global object, and primitive values will be boxed.

The other answers provide detailed information about when autoboxing occurs, but here's a couple more things to remember:
Autoboxing does not occur when using the in operator, which throws a TypeError if the value received is not an object. A simple solution is to manually box the object with Object(value).
Some form of autoboxing occurs when iterating using for...of or the spread syntax [...value] which allows strings to be iterated.

Related

When using bind() on a Javascript number, what does the console.log() output represent?

I came across a tutorial on bind() and the output is [Number: 1]. Why is the number represented like this when logged as the context of the bind function?
const func = function() {
console.log(this)
}.bind(1);
func();
Thanks!
Bind sets the "this" property to whatever the argument is that it is passed. In this case, since 1 is a primitive it is wrapped in the Number object (this is how JS handles primitives being used as objects) so the this context is the Number object containing 1.
The first parameter of bind is the target to bind to the function.
In this case a number literal is supplied.
Internally, bind boxes the number literal into a Number object, equivalent to Number(1).
This object is then printed to the console.
Where, internally, bind performs the boxing, I am unsure.
In the spec the operation BoundFunctionCreate assigns the new target to the [[BoundThis]] internal slot.
9.4.1.3 BoundFunctionCreate ( targetFunction, boundThis, boundArgs )
The abstract operation BoundFunctionCreate with arguments targetFunction, boundThis and boundArgs is used to specify the creation of new Bound Function exotic objects. It performs the following steps:
Assert: Type(targetFunction) is Object.
Let proto be ? targetFunction.[GetPrototypeOf].
Let obj be a newly created object.
Set obj's essential internal methods to the default ordinary object definitions specified in 9.1.
Set obj.[[Call]] as described in 9.4.1.1.
If IsConstructor(targetFunction) is true, then
Set obj.[[Construct]] as described in 9.4.1.2.
Set obj.[[Prototype]] to proto.
Set obj.[[Extensible]] to true.
Set obj.[[BoundTargetFunction]] to targetFunction.
Set obj.[[BoundThis]] to boundThis.
Set obj.[[BoundArguments]] to boundArgs.
Return obj.

Searching toFixed with "in" operator - How does the "in" operator work on primitives?

I started reading YDKJS for fun - and found that he's written:
we can do stuff like:
var num = (1.2).toFixed(1)
so - this means that toFixed is being invoked as a member method from an integer value.
So why doesn't this work??
"toFixed" in 1.222
But this works:
"toFixed" in new Number(1.222)
Page 268 of the Es262 spec states:
RelationalExpression : RelationalExpression in ShiftExpression
[...]
Let rref be the result of evaluating ShiftExpression.
Let rval be ? GetValue(rref).
If Type(rval) is not Object, throw a TypeError exception.
So in other words: You can't use in on numbers. Thats just the way it is defined.
new Number however does not create a number, but a number object (an object that inherits from the Number.prototype). That's why you can use in on it, cause its an actual object.
You can still do 12..toFixed(), thats because of a very interesting construct in the spec: The abstract GetValue operation, which will be called when you access a property¹, does call toObject if the target (12 in this case) is not an object, and that will then do the following:
Return a new Number object whose [[NumberData]] internal slot is set to argument.
So in other words: 12..toFixed() is exactly the same as new Number(12).toFixed().
¹ interestingly accessing the property itself does not actually do that according to the spec, if you do a.b that will only look up the value of a and create a reference (Reference(a, "b")). The actual property lookup happens when GetValue gets called on it (however I don't know of any case were a Reference gets lost without calling GetValue on it).

JavaScript Make a non-object variable with properties [duplicate]

I've been messing around with the ECMA-262 standard (ECMAScript Language Specification, 3rd edition, if it matters for this - I have not found any difference between the 3rd and 5th edition on String Type / String Object).
There's one thing that baffles me: the difference between the String Type and the String Object. Yes I know the difference in the sense that the String Type is a sequence of 16-bit UTF-16 units and the String Object is a built-in object with its internal Class property set to "String" and its internal Value property set to a value of the String Type.
But reading the specification, the string type does not seem to expose any methods; that is, it's just a value without any additional properties. Take this code, everything is exactly as expected:
document.writeln(typeof "foo"); // 'string'
document.writeln(typeof new String("foo")); // 'object'
The first type is the actual String Type and the second is the Object Type (it's an object of class String, but its data type is object). However, looking at this:
"foo".charAt(0);
fooStrObj = new String("Foo");
fooStrObj.charAt(0);
They both seem to expose the same functions, but there are no functions on the String Type defined in the ECMA-262 standard; all the functions it exposes are from the String.prototype object (and I can see no reference to the fact that the String Type magically exposes all the properties and functions of the String.prototype object in the ECMA-262 standard). So are the values of type String Type automatically promoted to a String Object with the original String Type value as its internal Value property?
And if they are treated exactly the same (which for all intents and purposes they seem to be), why have two different ways to represent a String?
Strings are a value type in JS, so they can't have any properties attached to them, no prototype, etc. Any attempt to access a property on them is technically performing the JS [[ToObject]] conversion (in essence new String).
Easy way of distinguishing the difference is (in a browser)
a = "foo"
a.b = "bar"
alert("a.b = " + a.b); //Undefined
A = new String("foo");
A.b = "bar";
alert("A.b = " + A.b); // bar
Additionally while
"foo" == new String("foo")
is true, it is only true due to the implicit type conversions of the == operator
"foo" === new String("foo")
will fail.
It's analogous to the difference between int and Integer in Java.
According to the standard, strings are automatically converted to String objects when you try to call a method. See ECMA 262-3 section 11.2.1; step 5 calls ToObject (which is defined in section 9.9).
11.2.1 Property Accessors
[...]
The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows:
Evaluate MemberExpression.
Call GetValue(Result(1)).
Evaluate Expression.
Call GetValue(Result(3)).
Call ToObject(Result(2)).
Call ToString(Result(4)).
Return a value of type Reference whose base object is Result(5) and whose property name is Result(6).
9.9 ToObject
The operator ToObject converts its argument to a value of type Object according to the following table:
[...]
Create a new String object whose [[value]] property is set to the value of the
string. See 15.5 for a description of String objects.
As a specification technique, this is a hack to explain how strings can appear to have methods even though they're not really objects.
Apart from that, the wrapper objects are not very useful. I don't know why they're in the language. I rather wish they weren't. :)

What is the difference between JavaScript object and primitive types?

Stoyan Stefanov in his excellent book 'Object-Oriented JavaScript' says:
Any value that doesn't belong to one of the five primitive types listed above is an object.
With five primitive types he means Number, String, Boolean, Undefined and Null. However in Google Chrome console it seems like number is not primitive type at all (compared to C primitive types like int). It looks like the primitive number has methods:
var a = 2.2;
console.log(a.toFixed()); // logs "2"
Thus I assumed that I can work with number as with an object, so I tried to assign a property to it:
var a = 2;
a.foo = 'bar';
console.log(a.foo); // logs undefined
I don't understand that behavior. If number has a method, it should behave like object, shouldn't it? It even has a prototype:
Number.prototype.foo = 'bar';
var a = 2;
console.log(a.foo); // logs 'bar'
So what is the magic behind this? How JavaScript treats objects versus primitive types? I would rather not use the word primitive and substitute it with simple objects. As I see it those are objects which can't be extended with new properties, however they are constructed through their constructor and also have prototype which can be extended like with normal objects.
[...] It looks like the primitive number has methods
The primitive, does not actually has its own properties. It gets coerced to an object in order to be able to access "its" properties. The coerced object is not accessable outside the called Method *(In strict mode even not inside the method)*. As such, the referenced variable is always a primitive.
Consider this simple example:
Number.prototype.myTypeInAMethod = function () {
console.log (typeof this.valueOf ()) //"number" => The primitive is wrapped in an object.
return typeof this;
}
var num = 123;
typeof num; //number
num.myTypeInAMethod () //object
side note: In ES5s strict mode,this would be a primitive and the type would be number
Since the variable num is a primitive, you can not assign values to it.
num.foo = "bar";
num.foo //undefined
If you instead create a number (or string) via its object constructor, its type indeed is an object.
A quick check by adding a property shows it can actually be assigned.
var objNum = new Number(123);
typeof objNum ; //"object"
objNum.foo = "bar";
objNum.foo //"bar"
So what is the magic behind this? How JavaScript treats objects versus primitive types?
This process is described in ES5 §8.7.1 GetValue
For an object:
If Type(V) is not Reference, return V.
Let base be the result of calling GetBase(V).
If IsUnresolvableReference(V), throw a ReferenceError exception.
If IsPropertyReference(V), then
If HasPrimitiveBase(V) is false, then let get be the [[Get]] internal method of base, otherwise let get be the special [[Get]] internal method defined below.
Return the result of calling the get internal method using base as its this value, and passing GetReferencedName(V) for the argument.
Else, base must be an environment record.
Return the result of calling the GetBindingValue (see 10.2.1) concrete method of base passing GetReferencedName(V) and IsStrictReference(V) as arguments.
For a primitive:
The following [[Get]] internal method is used by GetValue when V is a property reference[1] 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.
[1] IsPropertyReference(V). Returns true if either the base value is an object or HasPrimitiveBase(V) is true; otherwise returns false.

Primitives and Objects

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 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.
Would Primitive Object be more accurate then Object when defining
String, Boolean, and Number?
Please note that I'm not saying that numbers are not objects here, I'm pointing out that it appears ambiguous. This is the kind of thing that confuses JavaScript newcomers.
The distinction is mostly academic, but there is one case where it seems ambiguous: literals represent primitive objects except when the literal appears to represent a number. You can't apply a method directly to a literal integer* symbol:
1.toString();
SyntaxError: identifier starts immediately after numeric literal
…but you can apply methods of Numbers:
Number(1).toString();
'1'
…and a name that contains a number is a Number:
x = 4;
x.toString();
'4'
I think this is actually a parsing problem, but I don't really know why the parser can't tell that 1 is a Number as easily as it can tell that "abc" is a String. I suppose it has to do with the semantic ambiguity of the . symbol. (Is it a decimal point or a method operator?)
*JavaScript doesn't actually have integers. I just mean a symbol that consists entirely of [0-9]+.

Categories

Resources