When judging the function type, we usually use the typeof method. Under normal circumstances, it will get the effect we expected. However, there are some details that are not well known to us. After analyzing these details, John Resig provided us with a perfect solution, which will be introduced in detail in this article:
1. Unknown details of traditional methods
There is no doubt that when determining the function type, we use the typeof method, such as:
function fn(){
//content
}
alert(typeof fn)//The result is "function".
However, this method doesn't work as expected in some browsers.
1. Firefox2 and Firefox3
In these two browsers, using typeof to detect the type of an HTML object element results in an imprecise "function" result instead of "object", such as HTMLDocument. like:
alert(typeof HTMLDocument);
//In Firefox2 the result is "function";
//In Firefox3 the result is "object";
2. Firefox2
For regular expressions, the result returned in this browser is "function" (the result is "object" in Firefox3), such as:
var reg = /test/;
alert(typeof reg);
//In Firefox2 the result is "function";
//In Firefox3 the result is "object";
Note: I tested it in Safari, and the result was also "function".
3. IE6 and IE7
When using the typeof method on a DOM element in IE, the result is "object". like:
alert(typeof document.getElementsByTagName("body")[0].getAttribute);
//The result is "object"
4. Safari 3
Safari thinks that the NodeList of DOM elements is a function, such as:
alert(typeof document.body.childNodes);
//The result is "function"
Obviously, if you want to test whether an object is a function, using the typeof method does not guarantee the test result in a real sense. Then, we need a solution that guarantees test results in all browsers. We know that the function itself has two methods, apply() and call(), but these two methods do not exist in the problematic function in IE. Try the following test:
alert(typeof document.getElementsByTagName("body")[0].getAttribute.call)
//The result is "undefined" in IE
Obviously, we cannot take advantage of these two methods.
2. Perfect solution and implementation process
John Resig provided us with a perfect solution. This complex but stable method of determining whether an object is a function is as follows:
function isFunction( fn ) {
return !!fn && !fn.nodeName && fn.constructor != String &&
fn.constructor != RegExp && fn.constructor != Array &&
/function/i.test( fn + "" );
}
This function first ensures that the test object exists and serializes it into a string containing "function". This is the basis of our detection (fn.constructor != String, fn.constructor != Array, and fn.constructor != RegExp ). In addition, we need to ensure that the declared function is not a DOM node (fn.nodeName). Then, we can do the toString test. If we convert a function to a string, in a browser (fn+"") gives us the result like this "function name(){...}". Now, determining whether it is a function is as simple as checking whether the string contains the word "function". This works wonders, for any function in question, we get the results we need in all browsers. Compared with the traditional method, the running speed of this function is somewhat unsatisfactory. The author recommends that we use it conservatively.
John Resig is the developer of the jQuery library. I believe that friends who use this library are familiar with its concise syntax and excellent performance. In addition to pursuing code simplicity and high performance, the author's spirit of perfection is also impressive. If you are a perfectionist, I believe this article will be helpful to you.
Original text: http://www.denisdeng.com/?p=426