JavaScriptで関数をテストする最良の方法は?
-
03-07-2019 - |
質問
これについてはかなりの研究を行ってきましたが、使用されている方法は一貫性がなく、多様であるようです。
過去に使用したいくつかの方法を次に示します。
/* 1: */ typeof myFunc === 'function'
/* 2: */ myFunc.constructor === Function
/* 3: */ myFunc instanceof Function
研究の一環として、いくつかの有名なライブラリがこれをどのように達成したかを見てきました:
/* jQuery 1.2.6: */ !!fn && typeof fn != "string" && !fn.nodeName && fn.constructor != Array && /^[\s[]?function/.test( fn + "" )
/* jQuery 1.3b1: */ toString.call(obj) === "[object Function]"
/* Prototype 1.6: */ typeof object == "function"
/* YUI 2.6: */ typeof o === 'function'
非常に多くの異なる方法が使用されていることに驚いていますが、確かに単一の許容可能なテストが合意されていますか?また、jQuery 1.2.6のレンディションの意図が何であるかについてはまったくわかりません。少しOTTに見えます...
だから、私の質問は残っていますが、関数をテストする最良の方法は何ですか?
上記のメソッドのいくつか、特にjQuery 1.2.6についての洞察をいただければ幸いです。 (私は彼らが何をしているかを見ることができます、それは奇妙に思えます)
[*]「最良」とは、最も広く受け入れられているクロスブラウザ互換の方法を意味します。
編集:はい、それは以前に議論されたことを知っていますが、最も効果的な方法についての議論がまだ欲しいです。なぜこれほど多くの異なる方法が使用されているのですか?
SOに関するこれまでの議論では、(ほとんど)typeof演算子についてのみ言及しましたが、代替メソッドの有効性を示唆するものはいませんでした。
解決
オブジェクトが関数かどうかをテストする最良の方法は、 typeof myFunc === 'function'
です。ライブラリを使用している場合は、そのライブラリの機能テスト jQuery.isFunction(myFunc)
を使用します。
typeof
を使用すると、Things が関数として誤報告される可能性があります。これは非常にまれですが、これらの不整合を解消するためにライブラリがあります。これらの問題を回避するjQuery:
- Firefoxは
typeof document.createElement(" object")
で関数を報告します
- Safariは
typeof document.body.childNodes
を使用して関数をレポートします
- 古いバージョンのFirefoxは、正規表現を関数として報告しました(3.0の場合はそうではありません)。
- グローバル関数(
alert
)に組み込まれたIEおよび一部のノードメソッド(getAttribute
)は、" object"型であると報告されています。
typeof
ではなく instanceof
を使用すると、これらの一部を回避できます。たとえば、Firefoxでは document.createElement(" object")instanceof Function
は false
です。
元のチケット(#3618)<のコメントで最初のメソッドの誕生を表示できます。新しいメソッドは changeset 5947 からのものであり、 IEメモリリーク。おそらく遅いですが、小さく、きれいです。
ここでは、==と===の動作に大きな違いはありませんが、厳密な評価は非常にわずかに高速であるため、優先されます。
他のヒント
jQueryの開発者であるJohn Resigは、jQueryの内部で奇妙な選択をしたようです。
toString.call(obj) === "[object Function]"
非常にきれいに見えますが、単純な typeof
アプローチが失敗する場合に上記が当てはまる状況を考えることはできませんが、おそらく彼は残りの使用法ではないことを知っています。
typeof o === "function"
動作しないという強力な証拠がない限り、より明確になっているため、後者を使用します。
両方のオペランドが文字列であるため、 typeof
で厳密な等価性を使用する理由いくつかの問題を見落としていますか?
とにかく、私はtypeofのより簡単な方法に行きます。 instanceof
も読み取り可能ですが、関数はオブジェクトであるという事実をより強く主張しているようです。これは問題とは無関係かもしれません。