The question is whether the value is primitive or boxed

typeof can be used to determine if 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 TJCrowder comment .

Should we ever care about whether our value is primitive or boxed?

+16
javascript boxing typeof
Jul 22 '11 at 16:40
source share
3 answers

I would say that it makes almost no sense, you almost do not care if you are dealing with the primitive string or string .

There are regional cases. For example, a string object is an actual object, you can add properties to it. This allows you to do such things:

 function test(arg) { arg.foo = "bar"; } 

If the call code passes in the string primitive:

 var s1 = "str"; test(s1); 

... arg gets the status of string and gets the property added to it, but this string object is not used by anything after test returned.

In contrast, if the call code passes in a string object:

 var s2 = new String("str"); test(s2); 

... then the property is added to this object, and the calling code can see it. Consider ( live copy ):

 var s1, s2; s1 = "str"; display("[Before] typeof s1.foo = " + typeof s1.foo); test(s1); display("[After] typeof s1.foo = " + typeof s1.foo); s2 = new String("str"); display("[Before] typeof s2.foo = " + typeof s2.foo); test(s2); display("[After] typeof s2.foo = " + typeof s2.foo); function test(arg) { arg.foo = "bar"; } 

Output:

  [Before] typeof s1.foo = undefined
 [After] typeof s1.foo = undefined
 [Before] typeof s2.foo = undefined
 [After] typeof s2.foo = string 

Note that s2.foo is a string, but s1.foo not (since s1 was a string primitive, the object created when we push it to test has nothing to do with the calling code).

Is there any precedent for this? I do not know. I would say that it will be a very sharp edge, if so.

+7
Jul 22 '11 at 16:50
source share

All things toString seem to be an attempt at workarounds with interfacing mixing different built-in String constructors. This is not necessary to check if something is a primitive string - typeof enough, so it makes no sense to use for is_primitive_string .

I very rarely see arguments passed as String instances, so I can’t understand why I would need to check if something is a single Cross-frame of String instead of just resorting to the String value through ("" + s) or String(s) . The only time I used the String value in production code was that I needed an empty string that was true in some highly optimized code .

As for the rest, instances of the Boolean class do not behave as might be expected in conditions.

 if (new Boolean(false)) { alert("WTF!"); } else { alert("OK"); } Boolean.prototype.not = function () { return !this; }; if (new Boolean(false).not()) { alert("OK"); } else { alert("Really, WTF!"); } if (false.not()) { // Autoboxing alert("OK"); } else { alert("Cmon, WTF!"); } 

!(false) is true , but when you use to create an instance of the Boolean class, the operator ! applies to the value of the object, and the values ​​of the object are always true.

I believe that strict mode EcmaScript 5 changes the way this done, so the last example ( false.not() ) will behave as you would naively expect when "use strict"; is added to the beginning of Boolean.prototype.not in valid ES5.

With Number s, comparisons using < are OK, and addition and other operators tend to work as expected. new Number(0) and new Number(NaN) have the same problems as new Boolean(false) around conditions, and of course

 alert(NaN === NaN); // false var NAN = new Number(NaN); alert(NAN === NAN); // true 

and === and !== compared by reference for all String , Number and Boolean .

+3
Jul 22 2018-11-22T00:
source share

I use underscore.js methods to determine the type of a variable. Try using: isEmpty, isElement, isArray, isArguments, isFunction, isString, isNumber, isBoolean, isDate, isRegExp isNaN, isNull, isUndefined

Described here: http://documentcloud.github.com/underscore/

-2
Jul 22 '11 at 16:45
source share



All Articles