Javascript 判断函数类型完美解决方案

 更新时间:2009年09月02日 00:51:00   作者:  
在判断函数类型时,我们通常使用typeof方法,一般情况下,它会得到我们所预想的效果。
但是,有一些细节并不为我们所熟知。John Resig 在分析了这些细节之后,为我们提供了一个完美的解决方案,本文将作详细介绍:

一、传统方法不为人所知的细节
毫无疑问,在判断函数类型时,我们使用的是typeof方法,比如:
复制代码 代码如下:

function fn(){
//content
}
alert(typeof fn)//结果是"function"。

但是,该方法在一些浏览器中并不是像我们想像的那样工作。

1、Firefox2和Firefox3
在这两个浏览器中,用typeof检测HTML对象元素的类型,得到是一个不精确的“function”结果,而不是“object”,如HTMLDocument。如:
复制代码 代码如下:

alert(typeof HTMLDocument);
//在Firefox2中结果是"function";
//在Firefox3中结果是"object";

2、Firefox2
对于正则表达式,在该浏览器中返回的结果是“function”(在Firefox3中结果是“object”),如:
复制代码 代码如下:

var reg = /test/;
alert(typeof reg);
//在Firefox2中结果是"function";
//在Firefox3中结果是"object";

注:本人在safari中测试,其结果也是“function”。
3、IE6和IE7
在IE中对DOM元素使用typeof方法,得到的结果是“object”。如:
复制代码 代码如下:

alert(typeof document.getElementsByTagName("body")[0].getAttribute);
//结果是"object"

4、Safari 3
safari认为DOM元素的NodeList是一个函数,如:
复制代码 代码如下:

alert(typeof document.body.childNodes);
//结果是"function"

很明显,如果你要测试一个对象是否为函数,使用typeof方法并不能从真正意义上保证测试结果。那么,我们就需要一种在所有浏览器中都能保证测试结果的解决方案。我们知道function本身有apply()和call()两种方法,但这两个方法在IE中存在问题的函数中并不存在,试试下面的测试:
复制代码 代码如下:

alert(typeof document.getElementsByTagName("body")[0].getAttribute.call)
//在IE中结果是"undefined"

显然,我们不能利用这两个方法。

二、完美解决方案及实现过程
John Resig为我们提供了一个完美的解决方案,这个复杂但很稳定的判断一个对象是否为函数的方法如下:
复制代码 代码如下:

function isFunction( fn ) {
return !!fn && !fn.nodeName && fn.constructor != String &&
fn.constructor != RegExp && fn.constructor != Array &&
/function/i.test( fn + "" );
}

这个函数首先保证测试的对象存在,并将其序列化成含有“function”的字符串,这个是我们检测的基础(fn.constructor != String,fn.constructor != Array, and fn.constructor != RegExp)。另外,我们需要保证声明的函数不是一个DOM节点(fn.nodeName)。然后,我们就可以作toString测试。如果我们将一个函数转换成字符串,在一个浏览器中(fn+"")给我们的结果就像这样“function name(){...}”。现在,判断它是否为函数就很简单,仅仅只需要判断字符串中是否包含单词“function”。这很神奇,对于任何有问题的函数,在所有浏览器中都能得到我们所需要的结果。这个函数较之于传统的方法,运行速度有些不尽人意,作者建议我们保守使用。

John Resig 是jQuery库的开发者,相信使用该库的朋友们对该库简洁的语法和优秀的性能并不陌生。作者除追求代码简洁和性能高效之外,其尽善尽美的精神也让人叹服。如果你是一个完美主义者,相信此文对你很有帮助。

相关文章

  • Js判断参数(String,Array,Object)是否为undefined或者值为空

    Js判断参数(String,Array,Object)是否为undefined或者值为空

    在一些前端控件要提交数据到服务器端的数据验证过程中,需要判断提交的数据是否为空。如果是普通表单的字符串数据,只需要在 trim 后判断 length 即可,而这里需要的数据可以是各种不同的类型,通过 JSON.stringify(data) 进行序列化后再传递
    2013-11-11
  • Html和JS字符串中间加空格的简单实例

    Html和JS字符串中间加空格的简单实例

    最近遇到了个需求,需要在字符串的中间加上一两个字符串,所以下面这篇文章主要给大家介绍了关于Html和JS字符串中间加空格的相关资料,文中介绍的挺详细,需要的朋友可以参考下
    2023-02-02
  • JS实现图片产生波纹一样flash效果的方法

    JS实现图片产生波纹一样flash效果的方法

    这篇文章主要介绍了JS实现图片产生波纹一样flash效果的方法,通过递归调用自定义函数f_wave实现波纹效果,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • 微信小程序实现动态显示和隐藏某个控件功能示例

    微信小程序实现动态显示和隐藏某个控件功能示例

    这篇文章主要介绍了微信小程序实现动态显示和隐藏某个控件功能,涉及微信小程序事件响应及样式动态操作相关实现技巧,需要的朋友可以参考下
    2018-12-12
  • JS获取图片lowsrc属性的方法

    JS获取图片lowsrc属性的方法

    这篇文章主要介绍了JS获取图片lowsrc属性的方法,涉及javascript操作网页图片属性的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • js 日期比较相关天数代码

    js 日期比较相关天数代码

    这篇文章主要介绍了js实现日期比较相关天数的方法,需要的朋友可以参考下
    2014-04-04
  • Fetch超时设置与终止请求详解

    Fetch超时设置与终止请求详解

    这篇文章主要给大家介绍了关于Fetch超时设置与终止请求的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Fetch具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • JavaScript防止全局变量污染的方法总结

    JavaScript防止全局变量污染的方法总结

    这篇文章主要介绍了JavaScript防止全局变量污染的方法,结合实例形式较为详细的总结分析了JavaScript防止全局变量污染的常用操作技巧与注意事项,需要的朋友可以参考下
    2018-08-08
  • 获取当前网页document.url location.href区别总结

    获取当前网页document.url location.href区别总结

    请教:document.URL和window.location.href区别
    2008-05-05
  • 代码规范需要防微杜渐code review6个小错误纠正

    代码规范需要防微杜渐code review6个小错误纠正

    这篇文章主要为大家介绍了代码规范需要防微杜渐code review中的6个小错误纠正,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06

最新评论