JavaScript: converting any value to an object
This post is about converting between primitive values and wrapper objects [1]. Thankfully, one is usually not faced with this kind of task in JavaScript. The most frequent use case is to add properties to a primitive. As a primitive is immutable, you need to convert it to a wrapper object to do so. Read on if you want to see some of JavaScript’s more obscure corners.
Let us start with a short quiz:
What does ({}).valueOf.call(myvar) do?
Short answer: it converts any value to an object (an object remains unchanged, a primitive is converted to an instance of a wrapper type). The longer answer is as follows. The section numbers refer to the
ECMAScript 5 specification (ECMA-262, 5th edition).
- ({}).valueOf uses an instance of Object to access Object.prototype.valueOf.
- The call() method sets this to myvar and invokes Object.prototype.valueOf, without any (explicit) parameters.
- Object.prototype.valueOf (ECMA-262, 15.2.4.4) invokes the internal abstract operation ToObject (ECMA-262, 9.9). This operation converts a primitive to a (wrapper) object and leaves an object untouched. Thus, given a value, you always end up with an object.
This is a bit illogical, because in all subtypes of
Object,
valueOf() is about converting from a wrapper to a primitive (i.e., the opposite direction).
> String.prototype.valueOf.call(new String("abc"))
'abc'
> String.prototype.valueOf.call("abc")
'abc'
> "abc".valueOf()
'abc' // via String.prototype.valueOf()
> Object.prototype.valueOf.call("abc")
{ '0': 'a'
, '1': 'b'
, '2': 'c'
}
> Object.prototype.valueOf.call(new String("abc"))
{ '0': 'a'
, '1': 'b'
, '2': 'c'
}
So,
Object.prototype.valueOf.call() is verbose and not very intuitive for converting values to objects. A more descriptive alternative is the function
Object() (emphasis below is mine).
When Object is called as a function rather than as a constructor, it performs a type conversion [to an object]. [ECMA-262, 15.2.1]
Examples:
> Object("abc") instanceof String
true
> Object(new String("abc")) instanceof String
true
> Object(null)
{}
Using
Object as a constructor (with
new) basically has the same effect, but as a function, it better expresses the fact that there isn’t always a new object being created.
Related reading:
- JavaScript values: not everything is an object