序文Javascript でのデータ型の判断は、実は JavaScript の非常に基本的な問題ですが、日常のプログラミングでも面接でも非常によくある問題です。 ECMAScript 仕様では、合計 7 つのデータ型が定義されており、以下に示すように、基本型と参照型の 2 つのカテゴリに分類されます。
基本型は単純型とも呼ばれます。固定スペースを占有し、単純なデータ セグメントであるため、変数クエリ (つまり値によるアクセス) の速度を上げるためにスタックに格納されます。 参照型は複合型とも呼ばれます。その値のサイズは変化するため、スタックに格納することはできません。そうしないと、変数のクエリ速度が低下します。そのため、その値はヒープに格納され、変数に格納される値は、オブジェクトが格納されているメモリへのポインタ、つまりアドレスによるアクセスになります。参照型には、オブジェクトに加えて、関数、配列、正規表現、日付なども含まれます。 ECMAScript は緩く型付けされているため、特定の変数のデータ型を検出する方法が必要です。 JavaScript もこの問題に対するさまざまな方法を提供していますが、残念ながら、異なる方法では結果が異なります。 以下では、一般的に使用されている 4 つの方法を紹介し、各方法に存在する問題を簡単に分析します。 1. 型typeof は、右側に単項式を取り、その式のデータ型を返す演算子です。返される結果は、そのタイプの文字列 (すべて小文字) の形式で表現され、数値、ブール値、シンボル、文字列、オブジェクト、未定義、関数などの 7 つのタイプが含まれます。 typeof''; // 文字列は有効 typeof1; // 数値は有効 typeofSymbol(); // シンボルは有効 typeoftrue; // ブール値は有効 typeofundefined; // undefined は有効 typeofnull; // オブジェクトは無効 typeof[]; // オブジェクトは無効 typeofnewFunction(); // 関数は有効 typeofnewDate(); // オブジェクトは無効 typeofnewRegExp(); // オブジェクトは無効 typeof 演算子は、わかりにくいものの技術的には正しい値を返すことがあります。
その中で、null には独自のデータ型 Null があり、参照型の配列、日付、正規表現にも独自の特定の型があります。typeof がこれらの型を処理すると、プロトタイプ チェーンの先頭にある Object 型のみが返されます。これは正しいのですが、必要な結果ではありません。 2. インスタンスInstanceof は、A が B のインスタンスであるかどうかを判断するために使用されます。式は、A instanceof B です。A が B のインスタンスである場合は true を返し、そうでない場合は false を返します。 ここで重要なのは、instanceof がプロトタイプを検出することです。擬似コードを使用して、その内部実行プロセスをシミュレートします。 インスタンス(A,B) = { varL = A.__proto__; varR = B.プロトタイプ; もし(L === R) { // A の内部プロパティ __proto__ は B のプロトタイプ オブジェクトを指します returntrue; } falseを返します。 } 上記のプロセスから、A の __proto__ が B のプロトタイプを指している場合、A は B のインスタンスであると見なされることがわかります。さらにいくつかの例を見てみましょう。 [] 配列のインスタンス; // true {} オブジェクトのインスタンス; // true newDate() インスタンス Date; // true 関数 Person(){}; newPerson() は Person のインスタンスです。 [] インスタンスオブオブジェクト; // true newDate() インスタンスオブオブジェクト; // true newPerson インスタンスオブオブジェクト; // true instanceof は [] が Array のインスタンスであると判断できますが、[] は Object のインスタンスでもあると考えていることがわかりました。なぜでしょうか? []、配列、オブジェクトの関係を分析してみましょう。 instanceof から、[].__proto__ は Array.prototype を指し、Array.prototype.__proto__ は Object.prototype を指していることがわかります。最後に、Object.prototype.__proto__ は null を指し、プロトタイプ チェーンの終了を示します。したがって、[]、Array、および Object は内部的にプロトタイプ チェーンを形成します。 プロトタイプチェーンから、[] の __proto__ は直接 Array.prototype を指し、間接的に Object.prototype を指していることがわかります。したがって、instanceof の判定ルールによれば、[] は Object のインスタンスです。同様に、new Date() と new Person() も対応するプロトタイプ チェーンを形成します。したがって、instanceof は、2 つのオブジェクトがインスタンス関係にあるかどうかを判断するためにのみ使用できますが、オブジェクト インスタンスの特定のタイプを判断することはできません。 instanceof 演算子の問題は、グローバル実行コンテキストが 1 つだけであると想定していることです。 Web ページに複数のフレームが含まれている場合、実際には 2 つ以上の異なるグローバル実行環境が存在し、したがって 2 つ以上の異なるバージョンのコンストラクターが存在することになります。あるフレームワークから別のフレームワークに配列を渡す場合、渡された配列には、2 番目のフレームワークでネイティブに作成された配列とは別のコンストラクターがあります。 variframe = document.createElement('iframe'); document.body.appendChild(iframe); xArray = window.frames[0].Array; vararr = newxArray(1,2,3); // [1,2,3] arr 配列インスタンス; // false 配列のこの問題を解決するために、ES5 では Array.isArray() メソッドが提供されています。このメソッドは、オブジェクトが作成された環境に関係なく、オブジェクト自体が配列型であるかどうかを確認するために使用されます。 if(Array.isArray(値)){ //配列に対して何らかの操作を実行する} Array.isArray() は基本的にオブジェクトの [[Class]] 値を検出します。[[Class]] は、オブジェクトの型情報を含むオブジェクトの内部プロパティです。その形式は [object Xxx] で、Xxx は対応する特定の型です。配列の場合、[[Class]] の値は [object Array] になります。 3. コンストラクター関数 F が定義されると、JS エンジンは F にプロトタイプを追加し、プロトタイプにコンストラクター プロパティを追加して、F への参照を指すようにします。以下のように表示されます。 var f = new F()を実行すると、Fはコンストラクタとみなされ、fはFのインスタンスオブジェクトになります。このとき、Fプロトタイプ上のコンストラクタがfに渡されるため、f.constructor == Fとなります。 F はプロトタイプ オブジェクトのコンストラクターを使用して自分自身を参照していることがわかります。F をコンストラクターとして使用してオブジェクトを作成すると、プロトタイプのコンストラクターが新しく作成されたオブジェクトに継承されます。プロトタイプ チェーンの観点から見ると、コンストラクター F は新しいオブジェクトの型です。これを行うことの重要性は、新しいオブジェクトが誕生した後に追跡可能なデータ型を持つことができることです。 同様に、JavaScript の組み込みオブジェクトは内部的に次のように構築されます。 詳細:1. null と undefined は無効なオブジェクトなので、コンストラクタは存在しません。これら 2 種類のデータは、他の手段で判断する必要があります。 2. 関数コンストラクターは不安定です。これは主にカスタム オブジェクトに反映されます。開発者がプロトタイプを書き換えると、元のコンストラクター参照が失われ、コンストラクターはデフォルトで Object になります。 なぜオブジェクトになったのですか? prototype は new Object() のリテラル値である { } に再割り当てされるため、new Object() は Object プロトタイプのコンストラクターを Object 自体である { } に渡します。 そのため、開発を標準化するためには、オブジェクト インスタンスの型が改ざんされないように、オブジェクト プロトタイプを書き換えるときにコンストラクターを再割り当てすることが一般的に必要になります。 4. 文字列toString() は Object のプロトタイプ メソッドです。このメソッドが呼び出されると、デフォルトでは現在のオブジェクトの [[Class]] が返されます。これは、[オブジェクト Xxx] という形式の内部プロパティです。Xxx はオブジェクトのタイプです。 Object オブジェクトの場合、toString() を呼び出すだけで [object Object] が返されます。その他のオブジェクトの場合、正しい型情報を返すには、call / apply を通じて呼び出す必要があります。 Object.prototype.toString.call('') ; // [オブジェクト文字列] Object.prototype.toString.call(1); // [オブジェクト番号] Object.prototype.toString.call(true) ; // [オブジェクト ブール値] Object.prototype.toString.call(Symbol()); //[オブジェクトSymbol] Object.prototype.toString.call(undefined) ; // [オブジェクト Undefined] Object.prototype.toString.call(null) ; // [オブジェクト Null] Object.prototype.toString.call(newFunction()) ; // [オブジェクト関数] Object.prototype.toString.call(newDate()) ; // [オブジェクト Date] Object.prototype.toString.call([]) ; // [オブジェクト配列] Object.prototype.toString.call(newRegExp()) ; // [オブジェクト RegExp] Object.prototype.toString.call(newError()) ; // [オブジェクト Error] Object.prototype.toString.call(document) ; // [オブジェクト HTMLDocument] Object.prototype.toString.call(window) ; //[object global] windowはグローバルオブジェクトglobalへの参照です 要約するJS を使ってデータ型を判別する方法についての記事はこれで終わりです。JS データ型判別に関するより詳しい内容については、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Windows 64 ビットに MySQL を再インストールするチュートリアル (Zip バージョン、解凍バージョンの MySQL インストール)
>>: Linux で NFS ファイル共有サーバーを構築するための詳細な手順
水平方向では、行の配置を左、中央、右に設定できます。基本的な構文<TR ALIGN="...
1. Kali Linuxシステムのバージョンを確認するコマンド: cat /etc/issue 2...
Portainer は、Docker ホストと Docker Swarm クラスターの管理に使用でき...
以前、単純な UDP サーバーとクライアントの例を書きましたが、その中で、自分自身をクライアントと見...
次のような要件があります: インポート ボタン。ボタンをクリックして Excel テーブルをインポー...
MySQL データベースには増分バックアップ メカニズムはありませんが、マスター データベース内のす...
目次実際のプロジェクトで遭遇する要件実装が間違っているところもある私は個人的に、実装するより良い方法...
CSS3 の角丸や影の効果を使ったページを作りたいのですが、IE ブラウザでは対応していません。こ...
目次1. ヘルプコマンド2. ミラーコマンド3. コンテナコマンド1. ヘルプコマンド1. 現在のD...
目次1. 操作要素1.1. 要素コンテンツの変更1.2. innerText と innerHtml...
目次概要必要とするアプリURL PWA にはどのような技術コンポーネントが必要ですか?マニフェストフ...
目次1. はじめに2. axiosインターセプターを使用してフロントエンドログを出力する1. はじめ...
2.1、msiインストールパッケージ2.1.1、インストール特に重要なのは、インストール前に、元の ...
序文Linux 運用保守エンジニアとして、日々の業務の中で Linux サーバーの CPU 負荷が ...
1. クエリを最適化するには、テーブル全体のスキャンを避けてください。まず、where と orde...