Student
Student

Reputation: 28375

Why javascript's typeof always return "object"?

What's it used for if it always returns object as type?

always for Elements or lists.

Upvotes: 29

Views: 50919

Answers (8)

Ben Aston
Ben Aston

Reputation: 55779

typeof is an operator that accepts one operand, that returns a string indicating whether the operand is a primitive, a function, an object, or undeclared.

Note that typeof does not return strings that correspond to the name of the class or constructor function used to construct an object, hence your question.

typeof returns the following for the seven primitive JavaScript types:

  1. Undefined : 'undefined'
  2. Null : 'object'
  3. Boolean : 'boolean'
  4. Number : 'number'
  5. BigInt : 'bigint'
  6. Symbol : 'symbol'
  7. String : 'string'

(...and for the proposed BigDecimal primitive type, I presume it will return 'bigdecimal'.)

typeof returns the following for objects/object categories:

  1. document.all : 'undefined'
  2. functions : 'function'
  3. all other ordinary objects : 'object'

...and, finally, typeof returns 'undefined' for undeclared identifiers.

Notes

typeof returns 'object' for null, even though null is of type Null, due to an early requirement for easy interoperability with Java, a language in which null is the empty reference type. null sits at the top of every prototype chain, and can be thought of as being within the set of object-type primitives.

typeof returns 'function' for functions, and not 'object', to enable easy identification of functions (ie. callable objects) without having to expose within the language a separate isFunction or isCallable function.

typeof provides the ONLY mechanism in JavaScript to detect undeclared identifiers (see step 2a in the spec here) without throwing an error. This is useful when attempting to dynamically detect the host environment (eg. Node.js or a Web browser), where a tested-for identifier may or may not exist.

Attempting to use typeof with an identifier within a temporal dead zone throws a runtime error (ie. normal behavior).

document.all is an object in the Web platform (ie. not part of the language) for which typeof returns undefined. This anomaly is accommodated in the language specification in order to maintain compatibility with early Web browsers.

Primitive wrapper objects like new Number(1) and new Boolean(true) are treated as objects, not primitives. So, for example, typeof new Number(1) returns 'object'. Note that typeof Number(1) returns 'number' because without the new operator, these kind of constructor functions return an instance of the primitive.

typeof is an operator, not a function. Although it can be used with a syntax that looks like a bit like a function call (e.g. typeof(foo)), the right-had side of the expression is a normal unary expression: the parentheses do not delineate a function call, but an expression.

Upvotes: 1

Tamal Chowdhury
Tamal Chowdhury

Reputation: 542

Not all typeof returns objects.

Objects, Arrays and RegEx returns a type of object.

Function which is an object (reference type), yet returns type of function. That's an inconsistency in the language.

Another thing to note, undefined returns undefined while null returns object which is a bug in JS.

NaN (not a number) returns a type of number.

Better you keep track of all these and be aware of these strange behaviors.

For your reference here are all the type of values:

typeof "Tamal" ---> string
typeof 100 ---> number
typeof true ---> boolean
typeof false ---> boolean
typeof undefined ---> undefined
typeof function() {} ---> function
typeof Symbol() ---> symbol
typeof {name: "Tamal"} ---> object
typeof [1, 2, 3] ---> object
typeof /^/ ---> object
typeof NaN ---> number
typeof null ---> object (bug)

Upvotes: 7

James-Jesse Drinkard
James-Jesse Drinkard

Reputation: 15723

To add in with the others, typeof returns both objects and primitives. There are 5 primitive types in javascript: undefined, null, boolean, string and number. All else is an object. When typeof is applied to any object type other than Function, it simply returns “object”. When applied to a function, it returns a function object.

So, for example:

  • typeof true; //returns the primitive type "boolean"
  • typeof 123; //returns the primitive type "number"
  • typeof null //returns "object" which is a mistake, but so far there is no fix in another ECMAScript version, just talk about doing so.
  • typeof object //returns "object", which makes sense

To expound further on Pointy's answer, there is in every JavaScript object an internal property known as [[Class]] in ECMAScript 5. In order to display the actual value of the object, you can reference the [[Class]] property using: Object.prototype.toString. To avoid some of the specialized built-in objects overwriting toString you use the internal method of Call that will reveal the actual object type.

So instead of getting the generic object back from toString:

var dateObject = Object.prototype.toString(new Date);
document.write(dateObject);//[object Object]

You can get the actual object type using Call:

var dateObject = Object.prototype.toString.call(new Date);
document.write(dateObject);//[object Date]

Upvotes: 3

Grant Nyland
Grant Nyland

Reputation: 11

One needs to be a little careful with the typeof operator. It returns "object" for a null, "number" for NaN, "number" for Infinity, "object" for a "new Number(1)" and "object" for an array.

When checking for the existence of a variable (typeof variable !== "undefined") one sometimes needs to first check if (variable == null) because typeof returns "object" for a variable that is assigned to null.

This is a bit obvious but one also has to be careful not to invoke a function when checking typeof because the return type of the function will be reported and not "function".

Upvotes: 1

AutoSponge
AutoSponge

Reputation: 1454

In my experience, the main problem with typeof comes from distinguishing between arrays, objects, and nulls (all return "object").

To do this, I first check typeof then I check the null case or the "object's" constructor, like this:

for (o in obj) {
    if (obj.hasOwnProperty(o)) {
        switch (typeof obj[o]) {
            case "object":
                if (obj[o] === null) {
                    //do somethign with null
                } else {
                    if (obj[o].constructor.name === "Array") {
                        //do something with an Array
                    } else {
                        //do something with an Object
                    }
                }
                break;
            case "function":
                //do something with a function
                break;
            default:
                //do something with strings, booleans, numbers
                break;
        }
    }
}

Upvotes: 5

Achilles
Achilles

Reputation: 11319

You have to understand that the type system in JavaScript is dynamic with a few "primative" types to build upon. By treating all complex objects as the type "object" this allows you to duck-type and call methods without necessarily having to know the type of the object being passed around assuming that type has the function call implemented. In a dynamic programming language everything is an "object".

Upvotes: -1

Spudley
Spudley

Reputation: 168853

JS's typeof doesn't always return 'object', but it does return object for things which people may not consider to be objects -- ie arrays, and also, oddly, for nulls.

For arrays this is correct, because as far as JS is concerned, arrays are objects; they're the same thing. Array is just another class, and you can instantiate objects of type Array, but they're still treated as objects.

This page has a list of types in JS, along with the response you'll get for each of them from typeof. It also has some JS code to override the typeof function with one that returns more useful information. If you're worried about it not being useful, you could implement something like that if you wish.

Upvotes: 24

Pointy
Pointy

Reputation: 414086

It doesn't always return "object":

alert(typeof "hello");

That said, a (possibly) more useful trick to examine objects is to use Object.prototype.toString.call() and look at the result:

var t = Object.prototype.toString.call(itIsAMystery);

That will give you a string like [object Foo] with "Foo" being the constructor (I think) the interesting part. For "native" types (like Date or String) you get back that constructor name.

Upvotes: 11

Related Questions