Javascript 判斷函數(shù)類型完美解決方案
更新時(shí)間:2009年09月02日 00:51:00 作者:
在判斷函數(shù)類型時(shí),我們通常使用typeof方法,一般情況下,它會(huì)得到我們所預(yù)想的效果。
但是,有一些細(xì)節(jié)并不為我們所熟知。John Resig 在分析了這些細(xì)節(jié)之后,為我們提供了一個(gè)完美的解決方案,本文將作詳細(xì)介紹:
一、傳統(tǒng)方法不為人所知的細(xì)節(jié)
毫無(wú)疑問(wèn),在判斷函數(shù)類型時(shí),我們使用的是typeof方法,比如:
function fn(){
//content
}
alert(typeof fn)//結(jié)果是"function"。
但是,該方法在一些瀏覽器中并不是像我們想像的那樣工作。
1、Firefox2和Firefox3
在這兩個(gè)瀏覽器中,用typeof檢測(cè)HTML對(duì)象元素的類型,得到是一個(gè)不精確的“function”結(jié)果,而不是“object”,如HTMLDocument。如:
alert(typeof HTMLDocument);
//在Firefox2中結(jié)果是"function";
//在Firefox3中結(jié)果是"object";
2、Firefox2
對(duì)于正則表達(dá)式,在該瀏覽器中返回的結(jié)果是“function”(在Firefox3中結(jié)果是“object”),如:
var reg = /test/;
alert(typeof reg);
//在Firefox2中結(jié)果是"function";
//在Firefox3中結(jié)果是"object";
注:本人在safari中測(cè)試,其結(jié)果也是“function”。
3、IE6和IE7
在IE中對(duì)DOM元素使用typeof方法,得到的結(jié)果是“object”。如:
alert(typeof document.getElementsByTagName("body")[0].getAttribute);
//結(jié)果是"object"
4、Safari 3
safari認(rèn)為DOM元素的NodeList是一個(gè)函數(shù),如:
alert(typeof document.body.childNodes);
//結(jié)果是"function"
很明顯,如果你要測(cè)試一個(gè)對(duì)象是否為函數(shù),使用typeof方法并不能從真正意義上保證測(cè)試結(jié)果。那么,我們就需要一種在所有瀏覽器中都能保證測(cè)試結(jié)果的解決方案。我們知道function本身有apply()和call()兩種方法,但這兩個(gè)方法在IE中存在問(wèn)題的函數(shù)中并不存在,試試下面的測(cè)試:
alert(typeof document.getElementsByTagName("body")[0].getAttribute.call)
//在IE中結(jié)果是"undefined"
顯然,我們不能利用這兩個(gè)方法。
二、完美解決方案及實(shí)現(xiàn)過(guò)程
John Resig為我們提供了一個(gè)完美的解決方案,這個(gè)復(fù)雜但很穩(wěn)定的判斷一個(gè)對(duì)象是否為函數(shù)的方法如下:
function isFunction( fn ) {
return !!fn && !fn.nodeName && fn.constructor != String &&
fn.constructor != RegExp && fn.constructor != Array &&
/function/i.test( fn + "" );
}
這個(gè)函數(shù)首先保證測(cè)試的對(duì)象存在,并將其序列化成含有“function”的字符串,這個(gè)是我們檢測(cè)的基礎(chǔ)(fn.constructor != String,fn.constructor != Array, and fn.constructor != RegExp)。另外,我們需要保證聲明的函數(shù)不是一個(gè)DOM節(jié)點(diǎn)(fn.nodeName)。然后,我們就可以作toString測(cè)試。如果我們將一個(gè)函數(shù)轉(zhuǎn)換成字符串,在一個(gè)瀏覽器中(fn+"")給我們的結(jié)果就像這樣“function name(){...}”?,F(xiàn)在,判斷它是否為函數(shù)就很簡(jiǎn)單,僅僅只需要判斷字符串中是否包含單詞“function”。這很神奇,對(duì)于任何有問(wèn)題的函數(shù),在所有瀏覽器中都能得到我們所需要的結(jié)果。這個(gè)函數(shù)較之于傳統(tǒng)的方法,運(yùn)行速度有些不盡人意,作者建議我們保守使用。
John Resig 是jQuery庫(kù)的開發(fā)者,相信使用該庫(kù)的朋友們對(duì)該庫(kù)簡(jiǎn)潔的語(yǔ)法和優(yōu)秀的性能并不陌生。作者除追求代碼簡(jiǎn)潔和性能高效之外,其盡善盡美的精神也讓人嘆服。如果你是一個(gè)完美主義者,相信此文對(duì)你很有幫助。
一、傳統(tǒng)方法不為人所知的細(xì)節(jié)
毫無(wú)疑問(wèn),在判斷函數(shù)類型時(shí),我們使用的是typeof方法,比如:
復(fù)制代碼 代碼如下:
function fn(){
//content
}
alert(typeof fn)//結(jié)果是"function"。
但是,該方法在一些瀏覽器中并不是像我們想像的那樣工作。
1、Firefox2和Firefox3
在這兩個(gè)瀏覽器中,用typeof檢測(cè)HTML對(duì)象元素的類型,得到是一個(gè)不精確的“function”結(jié)果,而不是“object”,如HTMLDocument。如:
復(fù)制代碼 代碼如下:
alert(typeof HTMLDocument);
//在Firefox2中結(jié)果是"function";
//在Firefox3中結(jié)果是"object";
2、Firefox2
對(duì)于正則表達(dá)式,在該瀏覽器中返回的結(jié)果是“function”(在Firefox3中結(jié)果是“object”),如:
復(fù)制代碼 代碼如下:
var reg = /test/;
alert(typeof reg);
//在Firefox2中結(jié)果是"function";
//在Firefox3中結(jié)果是"object";
注:本人在safari中測(cè)試,其結(jié)果也是“function”。
3、IE6和IE7
在IE中對(duì)DOM元素使用typeof方法,得到的結(jié)果是“object”。如:
復(fù)制代碼 代碼如下:
alert(typeof document.getElementsByTagName("body")[0].getAttribute);
//結(jié)果是"object"
4、Safari 3
safari認(rèn)為DOM元素的NodeList是一個(gè)函數(shù),如:
復(fù)制代碼 代碼如下:
alert(typeof document.body.childNodes);
//結(jié)果是"function"
很明顯,如果你要測(cè)試一個(gè)對(duì)象是否為函數(shù),使用typeof方法并不能從真正意義上保證測(cè)試結(jié)果。那么,我們就需要一種在所有瀏覽器中都能保證測(cè)試結(jié)果的解決方案。我們知道function本身有apply()和call()兩種方法,但這兩個(gè)方法在IE中存在問(wèn)題的函數(shù)中并不存在,試試下面的測(cè)試:
復(fù)制代碼 代碼如下:
alert(typeof document.getElementsByTagName("body")[0].getAttribute.call)
//在IE中結(jié)果是"undefined"
顯然,我們不能利用這兩個(gè)方法。
二、完美解決方案及實(shí)現(xiàn)過(guò)程
John Resig為我們提供了一個(gè)完美的解決方案,這個(gè)復(fù)雜但很穩(wěn)定的判斷一個(gè)對(duì)象是否為函數(shù)的方法如下:
復(fù)制代碼 代碼如下:
function isFunction( fn ) {
return !!fn && !fn.nodeName && fn.constructor != String &&
fn.constructor != RegExp && fn.constructor != Array &&
/function/i.test( fn + "" );
}
這個(gè)函數(shù)首先保證測(cè)試的對(duì)象存在,并將其序列化成含有“function”的字符串,這個(gè)是我們檢測(cè)的基礎(chǔ)(fn.constructor != String,fn.constructor != Array, and fn.constructor != RegExp)。另外,我們需要保證聲明的函數(shù)不是一個(gè)DOM節(jié)點(diǎn)(fn.nodeName)。然后,我們就可以作toString測(cè)試。如果我們將一個(gè)函數(shù)轉(zhuǎn)換成字符串,在一個(gè)瀏覽器中(fn+"")給我們的結(jié)果就像這樣“function name(){...}”?,F(xiàn)在,判斷它是否為函數(shù)就很簡(jiǎn)單,僅僅只需要判斷字符串中是否包含單詞“function”。這很神奇,對(duì)于任何有問(wèn)題的函數(shù),在所有瀏覽器中都能得到我們所需要的結(jié)果。這個(gè)函數(shù)較之于傳統(tǒng)的方法,運(yùn)行速度有些不盡人意,作者建議我們保守使用。
John Resig 是jQuery庫(kù)的開發(fā)者,相信使用該庫(kù)的朋友們對(duì)該庫(kù)簡(jiǎn)潔的語(yǔ)法和優(yōu)秀的性能并不陌生。作者除追求代碼簡(jiǎn)潔和性能高效之外,其盡善盡美的精神也讓人嘆服。如果你是一個(gè)完美主義者,相信此文對(duì)你很有幫助。
相關(guān)文章
Js判斷參數(shù)(String,Array,Object)是否為undefined或者值為空
在一些前端控件要提交數(shù)據(jù)到服務(wù)器端的數(shù)據(jù)驗(yàn)證過(guò)程中,需要判斷提交的數(shù)據(jù)是否為空。如果是普通表單的字符串?dāng)?shù)據(jù),只需要在 trim 后判斷 length 即可,而這里需要的數(shù)據(jù)可以是各種不同的類型,通過(guò) JSON.stringify(data) 進(jìn)行序列化后再傳遞2013-11-11Html和JS字符串中間加空格的簡(jiǎn)單實(shí)例
最近遇到了個(gè)需求,需要在字符串的中間加上一兩個(gè)字符串,所以下面這篇文章主要給大家介紹了關(guān)于Html和JS字符串中間加空格的相關(guān)資料,文中介紹的挺詳細(xì),需要的朋友可以參考下2023-02-02JS實(shí)現(xiàn)圖片產(chǎn)生波紋一樣flash效果的方法
這篇文章主要介紹了JS實(shí)現(xiàn)圖片產(chǎn)生波紋一樣flash效果的方法,通過(guò)遞歸調(diào)用自定義函數(shù)f_wave實(shí)現(xiàn)波紋效果,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02微信小程序?qū)崿F(xiàn)動(dòng)態(tài)顯示和隱藏某個(gè)控件功能示例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)動(dòng)態(tài)顯示和隱藏某個(gè)控件功能,涉及微信小程序事件響應(yīng)及樣式動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-12-12Fetch超時(shí)設(shè)置與終止請(qǐng)求詳解
這篇文章主要給大家介紹了關(guān)于Fetch超時(shí)設(shè)置與終止請(qǐng)求的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Fetch具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05獲取當(dāng)前網(wǎng)頁(yè)document.url location.href區(qū)別總結(jié)
請(qǐng)教:document.URL和window.location.href區(qū)別2008-05-05代碼規(guī)范需要防微杜漸code?review6個(gè)小錯(cuò)誤糾正
這篇文章主要為大家介紹了代碼規(guī)范需要防微杜漸code?review中的6個(gè)小錯(cuò)誤糾正,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06