JavaScript の Typeof は実際には非常に複雑ですが、多くのことを行うために使用できますが、多くの奇妙な動作もあります。
この記事では、その複数の用途をリストし、既存の問題と解決策も指摘します。
この記事を読む前提は、プリミティブ値とオブジェクト値の違いを理解する必要があるということです。
変数が存在するかどうか、およびその変数に値があるかどうかを確認します
typeof は、次の 2 つの場合に「未定義」を返します。
1. 変数が宣言されていません
2. 変数の値は未定義です
例:
> 宣言された変数;
> 宣言された変数の型
'未定義'
> 未定義のタイプ
'未定義'
値が未定義かどうかを検出する方法は他にもあります。
true
翻訳者注: したがって、宣言されていない可能性のあるグローバル変数の存在を検出したい場合は、if(window.maybeUndeclaredVariable){} を使用することもできます。
解決策: この種の操作はあまり一般的ではないため、より良い解決策を見つける必要はないと考える人もいます。 しかし、おそらく誰かが特別な演算子を思いつくでしょう:
コードをコピーします
あるいは、変数が宣言されているかどうかを検出する演算子が必要な場合もあります:
コードをコピーします
翻訳者注: Perl では、上記で定義された演算子は defined() と同等であり、上記で宣言された演算子はexists() と同等です。
コードをコピーします
翻訳者注: これは元の JavaScript 実装のバグとしか言えず、これが現在の標準の規制方法です。 V8 では一度 typeof null === "null" を修正して実装しましたが、最終的には実行不可能であることが判明しました。 http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null。
(注釈: null を操作すると typeof は "object" を返します。これは JavaScript 言語自体のバグです。残念ながら、既存のコードがすでにこのパフォーマンスに依存しすぎているため、このバグは修正されることはありません。しかし、null はこの問題については stackoverflow で議論されています: http://stackoverflow.com/questions/801032/null-object-in-javascript/7968470#7968470@justjavac)
解決策: このタスクには typeof を使用せず、代わりに次のような関数を使用してください:
もう 1 つの可能性は、「デフォルト値演算子」を導入することです。この場合、myValue が定義されていない場合、次の式はdefaultValue を返します。
上記の式は次と同等です:
または:
は実際には次のステートメントを簡略化したものです:
bar などのネストされたプロパティにアクセスするときは、次の演算子の助けが必要になる場合があります:
obj または obj.foo が定義されていない場合、上記の式は例外をスローします。 演算子 .?? を使用すると、属性をレイヤーごとに移動するときに、値が未定義または null である最初に見つかった属性を返すことができます。
オブジェクト値とプリミティブ値を区別する
次の関数は、x がオブジェクト値かどうかを確認するために使用されます:
解決策: 次の方法もオブジェクト値の検出によく使用されます:
警告: ここで、instanceof Object を使用して検出できると思われるかもしれませんが、instanceof はオブジェクトのプロトタイプを使用してインスタンス関係を決定するため、プロトタイプのないオブジェクトをどうするか:
obj は確かにオブジェクトですが、値のインスタンスではありません:
実際には、そのようなオブジェクトに遭遇することはめったにないかもしれませんが、それは存在し、その用途があります。
翻訳者注: Object.prototype は、プロトタイプのない唯一の組み込みオブジェクトです。
プリミティブ値の型は何ですか?
typeof は、プリミティブ値の型を確認する最良の方法です。
問題: typeof null の奇妙な動作に注意する必要があります。
回避策: 次の関数でこの問題を解決できます (この使用例のみ)。
より良い解決策: getTypeName() 関数を実装します。この関数は、元の値の型を返すだけでなく、オブジェクト値の内部 [[Class]] 属性も返すことができます。 この関数の実装方法は次のとおりです (翻訳者注: jQuery の $.type はそのような実装です)
値が関数であるかどうか
typeof を使用して、値が関数であるかどうかを検出できます。
原則として、instanceof Function もこの要件を検出できます。 一見すると、よりエレガントな書き方に見えます。 ただし、ブラウザには癖があります。すべてのフレームとウィンドウに独自のグローバル変数があります。 したがって、あるフレームから別のフレームにオブジェクトを渡す場合、2 つのフレームのコンストラクターが異なるため、instanceof は正しく機能しません。 ECMAScript5 に Array.isArray() メソッドがあるのはこのためです。 オブジェクトが特定のコンストラクターのインスタンスであるかどうかをチェックするためのクロスフレームワーク メソッドがあれば便利です。 上記の getTypeName() は利用可能な回避策ですが、より根本的な解決策がある可能性があります。
概要
次に挙げるのは、現時点で JavaScript で最も緊急に必要とされる機能であり、typeof の現在の役割の一部の機能を置き換えることができます。
•isDefined() (Object.isDefined() など): 関数または演算子として使用できます
•isObject()
•getTypeName()
• オブジェクトが指定されたコンストラクターのインスタンスであるかどうかを検出するフレームワーク間のメカニズム
変数が宣言されているかどうかを確認するような要件の場合、独自の演算子は必要ない場合があります。