ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScriptにおけるtypeofの使い方入門_基礎知識

JavaScriptにおけるtypeofの使い方入門_基礎知識

WBOY
WBOYオリジナル
2016-05-16 17:37:311029ブラウズ

JavaScript の Typeof は実際には非常に複雑ですが、多くのことを行うために使用できますが、多くの奇妙な動作もあります。

この記事では、その複数の用途をリストし、既存の問題と解決策も指摘します。

この記事を読む前提は、プリミティブ値とオブジェクト値の違いを理解する必要があるということです。

変数が存在するかどうか、およびその変数に値があるかどうかを確認します
typeof は、次の 2 つの場合に「未定義」を返します。

1. 変数が宣言されていません

2. 変数の値は未定義です

例:

コードをコピーします コードは次のとおりです。

> undeclaredVariable === "未定義"
true

> 宣言された変数;
> 宣言された変数の型
'未定義'

> 未定義のタイプ
'未定義'

値が未定義かどうかを検出する方法は他にもあります。

コードをコピー コードは次のとおりです。

> >> 値 === 未定義
true

しかし、このメソッドが宣言されていない変数に対して使用されると、例外がスローされます。これは、typeof のみが、エラーを報告せずに宣言されていない変数を通常どおり検出できるためです。

コードをコピーします コードは次のとおりです。
> >参照エラー: undeclaredVariable が定義されていません



注: 初期化されていない変数、パラメータが渡されていない仮パラメータ、および存在しないプロパティには、常にアクセス可能で値が常に未定義であるため、上記の問題は発生しません。

コードをコピーします コードは次のとおりです。> ; 宣言された変数 = == 未定義
true

> (関数 (x) { return x === 未定義 }())
true
> ({}).foo === 未定義

true


翻訳者注: したがって、宣言されていない可能性のあるグローバル変数の存在を検出したい場合は、if(window.maybeUndeclaredVariable){} を使用することもできます。

問題: typeof はこのようなタスクを完了するのが非常に複雑です。

解決策: この種の操作はあまり一般的ではないため、より良い解決策を見つける必要はないと考える人もいます。 しかし、おそらく誰かが特別な演算子を思いつくでしょう:

コードをコピーします

コードは次のとおりです。> 定義された undeclaredVariablefalse
> var宣言された変数;
> 定義された宣言された変数
false



あるいは、変数が宣言されているかどうかを検出する演算子が必要な場合もあります:

コードをコピーします

コードは次のとおりです:> undeclaredVariablefalse
>宣言された変数;
>宣言された変数
true



翻訳者注: Perl では、上記で定義された演算子は defined() と同等であり、上記で宣言された演算子はexists() と同等です。

値が未定義または null に等しくないかどうかを判断する

問題: 値が定義されているかどうか (値が未定義でも null でもない) を検出したい場合、次のような問題が発生しました。 typeof の有名な奇妙な動作 (バグと考えられています): typeof null は "object" を返します:


コードをコピーします

翻訳者注: これは元の 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 を使用せず、代わりに次のような関数を使用してください:

コードをコピー コードは次のとおりです。

function isDefined(x) {
return x ! == null && x !== 未定義;
}

もう 1 つの可能性は、「デフォルト値演算子」を導入することです。この場合、myValue が定義されていない場合、次の式はdefaultValue を返します。

コードをコピー コードは次のとおりです:

myValue ??defaultValue

上記の式は次と同等です:

コードをコピー コードは次のとおりです。

(myValue !== unknown && myValue ! == null ) ? myValue :defaultValue

または:

コードをコピー コードは次のとおりです:

myValue ??=defaultValue

は実際には次のステートメントを簡略化したものです:

コードをコピーします コードは次のとおりです:

myValue = myValue

bar などのネストされたプロパティにアクセスするときは、次の演算子の助けが必要になる場合があります:

コードをコピー コードは次のとおりです:

obj.foo.bar

obj または obj.foo が定義されていない場合、上記の式は例外をスローします。 演算子 .?? を使用すると、属性をレイヤーごとに移動するときに、値が未定義または null である最初に見つかった属性を返すことができます。

コードをコピー コードは次のとおりです:
obj.??foo.??bar

上記の式は次と同等です:

コードをコピー コードは次のとおりです。
(obj === unknown || obj === null) ? obj
: (obj.foo === 未定義 || obj.foo === null) ? obj.foo
: obj.foo.bar

オブジェクト値とプリミティブ値を区別する

次の関数は、x がオブジェクト値かどうかを確認するために使用されます:

コードをコピー コードは次のとおりです。
function isObject(x) {
return (typeof x === "関数"
|| (typeof x === "オブジェクト" && x !== null));
}

問題: typeof は関数とオブジェクトを異なる型とみなし、typeof null は「object」を返すため、上記の検出はより複雑になります。

解決策: 次の方法もオブジェクト値の検出によく使用されます:

コードをコピー コードは次のとおりです。
function isObject2(x) {
return x = == Object(x);
}

警告: ここで、instanceof Object を使用して検出できると思われるかもしれませんが、instanceof はオブジェクトのプロトタイプを使用してインスタンス関係を決定するため、プロトタイプのないオブジェクトをどうするか:

コードをコピーします コードは次のとおりです。

> null);
> Object.getPrototypeOf(obj)
null

obj は確かにオブジェクトですが、値のインスタンスではありません:

コードをコピーします コードは次のとおりです。

> typeof obj
'object '
> オブジェクトのインスタンス
false

実際には、そのようなオブジェクトに遭遇することはめったにないかもしれませんが、それは存在し、その用途があります。

翻訳者注: Object.prototype は、プロトタイプのない唯一の組み込みオブジェクトです。

コードをコピー コードは次のとおりです。

>Object.getPrototypeOf(Object.prototype )
null
>Object.prototype のタイプ
'object'
>Object.prototype オブジェクトのインスタンス
false

プリミティブ値の型は何ですか?
typeof は、プリミティブ値の型を確認する最良の方法です。

コードをコピーします コードは次のとおりです。

> typeof "abc"
'文字列'
> 未定義のタイプ
'未定義'

問題: typeof null の奇妙な動作に注意する必要があります。

コードをコピー コードは次のとおりです。

> typeof null // 注意してください。
'オブジェクト'

回避策: 次の関数でこの問題を解決できます (この使用例のみ)。

コードをコピー コードは次のとおりです。

function getPrimitiveTypeName(x) {
var typeName = typeof x;
switch(typeName) {
case "未定義":
case "boolean":
case "number":
case "string":
return type Name;
case "object":
if (x === null) {
return "null";
}
default: // 以前の判定はどれも合格しませんでした
throw new TypeError ("パラメータはプリミティブ値ではありません: " x);
}
}

より良い解決策: getTypeName() 関数を実装します。この関数は、元の値の型を返すだけでなく、オブジェクト値の内部 [[Class]] 属性も返すことができます。 この関数の実装方法は次のとおりです (翻訳者注: jQuery の $.type はそのような実装です)

値が関数であるかどうか
typeof を使用して、値が関数であるかどうかを検出できます。

コードをコピー コードは次のとおりです。

> typeof function () {}
'関数'
> Object.prototype.toString
'関数'

原則として、instanceof Function もこの要件を検出できます。 一見すると、よりエレガントな書き方に見えます。 ただし、ブラウザには癖があります。すべてのフレームとウィンドウに独自のグローバル変数があります。 したがって、あるフレームから別のフレームにオブジェクトを渡す場合、2 つのフレームのコンストラクターが異なるため、instanceof は正しく機能しません。 ECMAScript5 に Array.isArray() メソッドがあるのはこのためです。 オブジェクトが特定のコンストラクターのインスタンスであるかどうかをチェックするためのクロスフレームワーク メソッドがあれば便利です。 上記の getTypeName() は利用可能な回避策ですが、より根本的な解決策がある可能性があります。

概要
次に挙げるのは、現時点で JavaScript で最も緊急に必要とされる機能であり、typeof の現在の役割の一部の機能を置き換えることができます。

•isDefined() (Object.isDefined() など): 関数または演算子として使用できます

•isObject()

•getTypeName()

• オブジェクトが指定されたコンストラクターのインスタンスであるかどうかを検出するフレームワーク間のメカニズム

変数が宣言されているかどうかを確認するような要件の場合、独自の演算子は必要ない場合があります。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。