I am trying to work my way through someone else's code and am finding some bizarre things. I found the following code in part of the program:
if(typeof func == "function" || (typeof func == "object" && typeof func.document == "undefined"))
{
func();
}
This made no sense to me, as I wasn't sure when such an event could happen? Could typeof return the wrong type? Or is it possible for a non-function object to be callable?
The code is a mess so I can't really find an example of where this particular check might succeed. I should note that the code may be upwards of 10 years old. The statement I received was that it was required because sometimes, when the code was originally written, a typeof was not returning function as a type.
Also, this check was required because sometimes func would be passed a window object (?) so it was necessary to make sure it wasn't a window object as well.
I am trying to work my way through someone else's code and am finding some bizarre things. I found the following code in part of the program:
if(typeof func == "function" || (typeof func == "object" && typeof func.document == "undefined"))
{
func();
}
This made no sense to me, as I wasn't sure when such an event could happen? Could typeof return the wrong type? Or is it possible for a non-function object to be callable?
The code is a mess so I can't really find an example of where this particular check might succeed. I should note that the code may be upwards of 10 years old. The statement I received was that it was required because sometimes, when the code was originally written, a typeof was not returning function as a type.
Also, this check was required because sometimes func would be passed a window object (?) so it was necessary to make sure it wasn't a window object as well.
Share Improve this question edited Jan 30, 2014 at 15:02 gen_Eric 227k42 gold badges303 silver badges342 bronze badges asked Jan 30, 2014 at 14:59 ColdFrogColdFrog 2151 silver badge13 bronze badges 6- 2 it seems possible from the given code that func could be anything – Huangism Commented Jan 30, 2014 at 15:03
-
7
This looks like a parameter check, to make sure the parameter given is a function before executing it as one. This hasn't much to do with typeof but more with the way the function gets called. The second part could have to do with older versions of IE, which for example gave "object" as result for the
window.alert
function. – gpgekko Commented Jan 30, 2014 at 15:05 -
I do understand what the code is actually doing, I think I was more concerned about how or why this could ever succeed if
func
was not actually a function. I think gpgekko may have nailed it though. It's entirely possible that this got passedwindow.alert
and if older IE didn't recognize that, this would have been necessary. – ColdFrog Commented Jan 30, 2014 at 15:11 -
typeof func == "object"
andfunc()
will lead to an error – metadings Commented Jan 30, 2014 at 15:16 -
@metadings: In modern web browsers. It might not have 10 years ago. Host objects are weird, and like gpgekko said, IE said
typeof alert === 'object'
, back in the day. – gen_Eric Commented Jan 30, 2014 at 15:17
2 Answers
Reset to default 7Remember: typeof
is for literals.
typeof undefined === "undefined"
typeof 5 === "number"
typeof true === "boolean"
typeof "" === "string"
typeof {} === "object"
typeof [] === "object"
typeof function { } === "function"
// null is a weird exception:
typeof null === "object"
instanceof
distinguishes when something is "of a Function" (notice that where typeof checks against string "object"
instanceof checks against Function Object
itself:
{} instanceof Object
function {} instanceof Object
function {} instanceof Function
[] instanceof Object
[] instanceof Array
As you see, typeof says === "function"
and !== "object"
: this can be misleading, because a function is also an object. This is when instanceof es into play.
Now, when you write a constructor, the constructed object is also instanceof your function:
// the constructor
function Example { }
// the object
var ex = new Example();
typeof Example === "function"
typeof ex === "object"
ex instanceof Object
ex instanceof Example
Using prototype you can also extend the chain, where typeof always says object:
function DerivedExample { }
DerivedExample.prototype = new Example();
// DerivedExample.prototype.constructor = DerivedExample;
var ex1 = new DerivedExample();
typeof DerivedExample === "function"
typeof ex1 === "object"
ex1 instanceof Object
ex1 instanceof Example
ex1 instanceof DerivedExample
So that's all about javaScript typeof
and also instanceof
. Hope it clarifies what's happening.
Something also good to know (this is not remended to be used in production code, but i've seen in also in CoffeeScript source afair):
typeof new Number(5) === "object"
new Number(5) instanceof Object
new Number(5) instanceof Number
typeof new Boolean("true") === "object"
new Boolean("true") instanceof Object
new Boolean("true") instanceof Boolean
typeof new String("") === "object"
new String("") instanceof Object
new String("") instanceof String
About functions and the window object:
Every standalone function will be called in context of window.
(Except) when you "use strict"
"directive", a standalone function will be called with context of undefined.
function world() {
// non-strict: this === window
// use-strict: this === undefined
}
world();
Now when you write a function as a member of an object, the function's context is the object:
var hello = {
world: function () {
// this === hello
}
};
hello.world();
This is also true for prototype functions, that are called in context of a newly constructed object:
function Hello() { }
Hello.prototype.world = function () {
// this instanceof Hello
// this will be === ex
};
var ex = new Hello();
ex.world();
And at least, you can change the context of any function using call
and apply
:
var ex = { };
function Example() {
// (1) non-strict: this === window
// (1) use-strict: this === undefined
// (2) this === ex
}
Example(); // (1)
Example.call(ex); // (2)
Example.apply(ex); // (2)
Consider this example
var a = [];
typeof a; // object
Object.prototype.toString.call(a); // [object Array]
var b = {};
typeof b; // object
Object.prototype.toString.call(b); // [object Object]
So yes, typeof
can be pretty confusing sometimes