JavaScript の Typeof は実際には非常に複雑ですが、多くの奇妙な動作もあります。また、この記事ではその複数の用途をリストし、既存の問題と解決策についても説明します。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FOperators%2Ftypeof
> タイプが未定義
'未定義'
> typeof null // 既知のバグ
'物体'
> true のタイプ
「ブール値」
>タイプ123
'番号'
>「abc」の種類
'弦'
> 関数の種類() {}
'関数'
> {} のタイプ
'物体'
> [] の種類
'物体'
> 未知の変数の種類
'未定義'
1. 変数が存在し、値があるかどうかを確認します。
typeof は、変数が宣言されていない場合と、変数の値が未定義の場合の 2 つの状況で「未定義」を返します。次に例を示します。
> typeof undeclaredVariable === "未定義" true > vardeclaredVariable > typeof undeclaredVariable '未定義' > typeof unknown'
値が未定義かどうかを検出する方法は他にもあります。
> 変数値 = 未定義; > 値 === 未定義 true
ただし、このメソッドが宣言されていない変数に対して使用されると、例外がスローされます。これは、typeof のみが、エラーを報告せずに宣言されていない変数を正常に検出できるためです。
> undeclaredVariable === 未定義 ReferenceError: undeclaredVariable が定義されていません
注: 初期化されていない変数、パラメータが渡されていない仮パラメータ、および存在しないプロパティには、常にアクセスでき、値が常に未定義であるため、上記の問題は発生しません。
> var宣言された変数; > 宣言された変数 === 未定義の真 > (関数 (x) { return x === 未定義 }()) 真 > ({}).foo === 未定義の真
翻訳者注: したがって、宣言されていない可能性のあるグローバル変数の存在を検出したい場合は、 if(window.maybeUndeclaredVariable){} を使用することもできます。
問題: typeof はそのようなタスクを実行するのが面倒です。
解決策: この種の操作はあまり一般的ではないため、より良い解決策を見つける必要はないと感じる人もいますが、おそらく誰かが特別な演算子を提案するでしょう。
> 定義された undeclaredVariable false > var宣言された変数 > 定義された宣言された変数 false;
あるいは、変数が宣言されているかどうかを検出する演算子も必要になるかもしれません。
> 宣言された undeclaredVariable が false > var 宣言された変数 > 宣言された変数が true;
翻訳者注: Perl では、上記の定義された演算子は defined() と同等であり、上記の宣言された演算子はexists() と同等です。
2. 値が未定義または null に等しくないかどうかを判断します。
問題: 値が定義されているかどうか (値が未定義でも null でもない) を確認したい場合、typeof の最も有名な癖 (バグと考えられています) の 1 つに遭遇します。それは、typeof null が「object」を返すというものです。
> null 'オブジェクト' の型
翻訳者注: これは、元の JavaScript 実装のバグであるとしか言えません。このようにして、V8 では標準化され、typeof null === "null" が実装されましたが、最終的には実行不可能であることが判明しました。 //wiki .ecmascript.org/doku.php?id=harmony:typeof_null
解決策: このタスクには typeof を使用せず、代わりに次のような関数を使用します。
関数 isDefined(x) { return x !== null && x !== 未定義 }
もう 1 つの可能性は、「デフォルト値演算子」を導入することです。この演算子では、myValue が定義されていない場合、次の式がdefaultValue を返します。
私の値 ??
上記の式は次と同等です。
(myValue !== 未定義 && myValue !== null) ?
または:
myValue ??= デフォルト値
実際、これは次のステートメントを簡略化したものです。
myValue = myValue ??
bar などのネストされたプロパティにアクセスするときは、この演算子の助けが必要になる場合があります。
obj.foo.bar
obj または obj.foo が未定義の場合、上記の式は例外をスローします。operator.?? を使用すると、プロパティをレイヤーごとに検索するときに最初に見つかった値を返すことができます。
obj.??foo.??バー
上記の式は次と同等です。
(obj === 未定義 || obj === null) ? obj : (obj.foo === 未定義 || obj.foo === null) ?
3. オブジェクト値とプリミティブ値を区別する
次の関数は、x がオブジェクト値かどうかをテストします。
function isObject(x) { return (typeof x === "関数" || (typeof x === "オブジェクト" && x !== null));
問題: typeof は関数とオブジェクトを異なる型とみなし、typeof null は「object」を返すため、上記の検出は複雑です。
解決策: 次の方法も、オブジェクト値の検出によく使用されます。
関数 isObject2(x) { return x === オブジェクト(x) }
警告: ここで、instanceof Object を使用して検出できると思われるかもしれませんが、instanceof はオブジェクトのプロトタイプを使用してインスタンスの関係を決定するため、プロトタイプのないオブジェクトはどうなるでしょうか。
> var obj = Object.create(null); > Object.getPrototypeOf(obj) null
obj は確かにオブジェクトですが、値のインスタンスではありません。
> オブジェクトのタイプ 'オブジェクト' > オブジェクトのオブジェクトのインスタンス false
実際には、そのようなオブジェクトに遭遇することはほとんどないかもしれませんが、それは存在し、その用途があります。
翻訳者注: Object.prototype はデフォルトで存在するオブジェクトであり、プロトタイプはありません。
>Object.getPrototypeOf(Object.prototype)null>Object.prototype'object' のタイプ>Object.prototype オブジェクトのインスタンス false
4.プリミティブ値の種類は何ですか?
typeof は、プリミティブ値の型を確認する最良の方法です。
> タイプ "abc" '文字列' > タイプ '未定義' '未定義'
問題: typeof null の奇妙な動作に注意する必要があります。
> typeof null // 'オブジェクト' に注意してください。
解決策: 次の関数でこの問題を解決できます (この使用例のみ)。
function getPrimitiveTypeName(x) { var typeName = typeof x; switch(typeName) { case "未定義": case "boolean": case "number": case "object": if (x == = null) { return "null"; } デフォルト: // 以前の判定はどれも合格しなかった throw new TypeError("パラメータはプリミティブ値ではありません: "+x);
より良い解決策: getTypeName() 関数を実装します。この関数は、元の値の型を返すだけでなく、オブジェクト値の内部 [[Class]] 属性も返すことができます。この関数の実装方法は次のとおりです (翻訳者注: jQuery $.type はそのような実装です)
5. 特定の値が関数であるかどうか
typeof は、値が関数であるかどうかを検出するために使用できます。 > typeof function () {} 'function' > typeof Object.prototype.toString 'function'
原則として、instanceof Function はこの要件を検出することもできます。一見、この記述方法はより洗練されているように見えますが、ブラウザには癖があります。したがって、特定のフレームを If に置くと、 object が別のフレームワークに渡されると、2 つのフレームワークのコンストラクターが異なるため、instanceof は正しく動作しません。 ECMAScript 5 に Array.isArray() メソッドが存在するのはこのためです。オブジェクトが特定のコンストラクターのインスタンスであるかどうかをチェックするためのクロスフレームワーク メソッドがあれば便利ですが、上記の getTypeName() は利用可能な回避策です。 , しかし、もっと根本的な解決策があるかもしれません。
6.概要
以下に挙げるのは、現時点で JavaScript で最も緊急に必要とされる機能であり、typeof の現在の役割の一部の機能を置き換えることができます。
isDefined() (Object.isDefined() など): 関数または演算子として使用できます。
isObject()
getTypeName()
オブジェクトが指定されたコンストラクターのインスタンスであるかどうかを検出するためのフレームワーク間のメカニズム
変数が宣言されているかどうかを確認する必要がある場合、それ自体の演算子は必要ありません。