One can use typeof
to determine whether a value is primitive or boxed.
Consider:
typeof "foo"; // "string"
typeof new String("foo"); // "object"
In combination with Object.prototype.toString
we could define the following two functions
var toString = Object.prototype.toString;
var is_primitive_string = function(s) {
return toString.call(s) === "[object String]" && typeof s === "string";
};
var is_boxed_string = function(s) {
return toString.call(s) === "[object String]" && typeof s === "object";
};
Are there any use cases for these two functions? (Or similar functions for Number
, Boolean
, etc).
The concept behind this question came from the following Comment by T.J.Crowder.
Should we ever care whether a value we have is primitive or boxed?
I'd say there's virtually no point, you almost never care whether you're dealing with a
string
primitive or aString
object.There are edge cases. For instance, a
String
object is an actual object, you can add properties to it. This lets you do things like this:If calling code passes in a
string
primitive:...
arg
gets promoted to aString
object and gets a property added to it, but thatString
object isn't used by anything aftertest
returns.In contrast, if calling code passes in a
String
object:...then the property is added to that object and the calling code can see it. Consider (live copy):
Output:
Note that
s2.foo
is a string, buts1.foo
isn't (becauses1
was a string primitive, the object created when we promoted it intest
has nothing to do with the calling code).Is there any use case for this? Dunno. I'd say it would be an extremely edgy edge case if so.
I use underscore.js methods to detect the type of the variable. Try to use: isEmpty, isElement, isArray, isArguments, isFunction, isString, isNumber, isBoolean, isDate, isRegExp isNaN, isNull, isUndefined
Described here: http://documentcloud.github.com/underscore/
All the
toString
stuff seems to be an attempt to workaround problems with cross-frame mixing of different builtinString
constructors. That is unnecessary for checking whether something is a primitive string --typeof
is sufficient, so there is no use case foris_primitive_string
.I very rarely see arguments passed as
String
instances so I can't see why I would need to check whether something is aString
instance cross-frame instead of just coercing to aString
value via("" + s)
orString(s)
. The only time I've ever used aString
value in production code was when I needed an empty string that was truthy in some highly optimized code.As far as the others go, instances of the
Boolean
class don't behave as one might expect in conditions.!(false)
istrue
, but when you use create an instance of theBoolean
class, the!
operator applies to the object value, and object values are always truthy.I believe EcmaScript 5 strict mode is changing the way
this
is presented so the last example (false.not()
) will behave as one might naively expect when"use strict";
is added to the top ofBoolean.prototype.not
in a valid ES5 interpreter.With
Number
s, comparisons using<
are OK and addition and other operators tend to work as expected.new Number(0)
andnew Number(NaN)
have the same problems asnew Boolean(false)
around conditions, and of courseand
===
and!==
compare by reference for all ofString
,Number
, andBoolean
.