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

相关文章

  • Extjs表单输入框异步校验的插件实现方法

    Extjs表单输入框异步校验的插件实现方法

    这篇文章主要介绍了Extjs表单输入框异步校验的插件实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-03-03
  • 最简单的JS实现json转csv的方法

    最简单的JS实现json转csv的方法

    这篇文章主要介绍了最简单的JS实现json转csv的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • 关于ExtJS4.1:快捷键支持的问题

    关于ExtJS4.1:快捷键支持的问题

    本篇文章小编为大家介绍,关于ExtJS4.1 快捷键支持的问题。需要的朋友参考下
    2013-04-04
  • JavaScript希尔排序、快速排序、归并排序算法

    JavaScript希尔排序、快速排序、归并排序算法

    这篇文章主要为大家详细介绍了JavaScript希尔排序、快速排序、归并排序算法,感兴趣的朋友可以参考一下
    2016-05-05
  • 详解JS如何处理可视区域图片懒加载技巧

    详解JS如何处理可视区域图片懒加载技巧

    这篇文章主要为大家介绍了JS如何处理可视区域图片懒加载技巧详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 详谈LABJS按需动态加载js文件

    详谈LABJS按需动态加载js文件

    为了提高页面的打开和加载速度,我们经常把JS文件放在页面的尾部,但是有些JS必须放在页面前面,这样就会增加页面的加载时间;于是出现了按需动态加载的概念,这个概念就是当页面需要用到这个JS文件或者CSS渲染文件的时候,在去请求这些文件,这样就节省了页面的加载时间
    2015-05-05
  • javascript在firefox下设为首页的代码

    javascript在firefox下设为首页的代码

    javascript在firefox下设为首页的代码...
    2007-09-09
  • js左侧多级菜单动态的解决方案

    js左侧多级菜单动态的解决方案

    实现的效果很简单,就是点一下显示,再点一下就隐藏,只不过是多了几级的问题。好,现在来说说我的设计思路,首先从第一级别开始,添加如下代码
    2010-02-02
  • js 函数性能比较方法

    js 函数性能比较方法

    在学习js过程中,经常会遇到同样一个功能点 这样实现也可以,那样实现也可以。但是哪个方式最优呢
    2020-08-08
  • JavaScript 异步调用框架 (Part 1 - 问题 & 场景)

    JavaScript 异步调用框架 (Part 1 - 问题 & 场景)

    在Ajax应用中,调用XMLHttpRequest是很常见的情况。特别是以客户端为中心的Ajax应用,各种需要从服务器端获取数据的操作都通过XHR异步调用完成。
    2009-08-08

最新评论