JS を使用してデータ型を決定する 4 つの方法

JS を使用してデータ型を決定する 4 つの方法

序文

Javascript でのデータ型の判断は、実は JavaScript の非常に基本的な問題ですが、日常のプログラミングでも面接でも非常によくある問題です。

ECMAScript 仕様では、合計 7 つのデータ型が定義されており、以下に示すように、基本型と参照型の 2 つのカテゴリに分類されます。

基本型: 文字列、数値、ブール値、シンボル、未定義、Null

参照タイプ: オブジェクト

基本型は単純型とも呼ばれます。固定スペースを占有し、単純なデータ セグメントであるため、変数クエリ (つまり値によるアクセス) の速度を上げるためにスタックに格納されます。

参照型は複合型とも呼ばれます。その値のサイズは変化するため、スタックに格納することはできません。そうしないと、変数のクエリ速度が低下します。そのため、その値はヒープに格納され、変数に格納される値は、オブジェクトが格納されているメモリへのポインタ、つまりアドレスによるアクセスになります。参照型には、オブジェクトに加えて、関数、配列、正規表現、日付なども含まれます。

ECMAScript は緩く型付けされているため、特定の変数のデータ型を検出する方法が必要です。 JavaScript もこの問題に対するさまざまな方法を提供していますが、残念ながら、異なる方法では結果が異なります。

以下では、一般的に使用されている 4 つの方法を紹介し、各方法に存在する問題を簡単に分析します。

1. 型

typeof は、右側に単項式を取り、その式のデータ型を返す演算子です。返される結果は、そのタイプの文字列 (すべて小文字) の形式で表現され、数値、ブール値、シンボル、文字列、オブジェクト、未定義、関数などの 7 つのタイプが含まれます。

typeof''; // 文字列は有効 typeof1; // 数値は有効 typeofSymbol(); // シンボルは有効 typeoftrue; // ブール値は有効 typeofundefined; // undefined は有効 typeofnull; // オブジェクトは無効 typeof[]; // オブジェクトは無効 typeofnewFunction(); // 関数は有効 typeofnewDate(); // オブジェクトは無効 typeofnewRegExp(); // オブジェクトは無効

typeof 演算子は、わかりにくいものの技術的には正しい値を返すことがあります。

  • null を除く基本型の場合、正しい結果を返すことができます。
  • 関数を除く参照型の場合、オブジェクト型が常に返されます。
  • null の場合はオブジェクト型を返します。
  • 関数の場合は関数の型を返します。

その中で、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 をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • js と jquery でデータ型を決定する 4 つの方法の概要
  • JavaScript でデータ型を判別する 4 つの方法
  • js データ型判定方法
  • js データ型とその判定方法の例
  • JSにおけるデータ型の正しい判定方法の例
  • JSにおける4つのデータ型判定方法
  • JavaScriptの型判定方法をいくつか紹介

<<:  Windows 64 ビットに MySQL を再インストールするチュートリアル (Zip バージョン、解凍バージョンの MySQL インストール)

>>:  Linux で NFS ファイル共有サーバーを構築するための詳細な手順

推薦する

読み取り専用と無効の違い

要約すると: Readonly は入力 (テキスト/パスワード) とテキスト領域に対してのみ有効です...

Nginx ベースの HTTPS ウェブサイトを設定する手順

目次序文:暗号化アルゴリズム: 1. HTTPS の概要2. NginxはHTTPSウェブサイト設定...

Webデザイン講座(4):素材と表現について

<br />前回のWebデザインチュートリアル:Webデザインチュートリアル(3):デザ...

Vue フロントエンド開発における階層的にネストされたコンポーネント間の通信の詳細な説明

目次序文例まとめ序文Vue の親子コンポーネントは、props を通じて親コンポーネントの値を子コン...

ウェブデザインにおける階層化インターフェースの設計経験

多くのネットユーザーは、なぜ自分のウェブサイトはいつも色の問題を抱えていて、いつも地味に見え、注目を...

CentOS7 インストール Zabbix 4.0 チュートリアル (イラストとテキスト)

SeLinuxを無効にするsetenforce 0永久に閉店: vi /etc/selinux/c...

VMware Workstation と vSphere 間で仮想マシンを移行する (画像とテキスト)

1. Workstationで仮想マシンのハードウェアバージョンを変更するWorkstation ...

elementui での el-cascader カスケードセレクタの実践

目次1. 効果2. メインコード1. 効果機能: インターフェイスから取得したデータを使用してオプシ...

Centos7 に mysql と mysqlclient をインストールする際に遭遇する落とし穴の概要

1. MySQL Yumリポジトリを追加するMySQL公式サイト>ダウンロード>MySQ...

MySQL テーブル フィールドの時間設定のデフォルト値

アプリケーションシナリオデータ テーブルでは、アプリケーションは各データがいつ作成されたかを記録する...

CSS レスポンシブ レイアウト システムの例コード

レスポンシブ レイアウト システムは、今日の一般的な CSS フレームワークではすでに非常に一般的で...

MySQL 5.7 のインストールと設定の詳細な手順

1. MySQLをダウンロードする1. MySQLの公式ウェブサイトにログインし、64ビットシステム...

HTML およびプラグイン アプリケーションにおけるデータ カスタム属性の使用の概要

HTML にはデータ属性が含まれていることがよくあります。これらは HTML5 のカスタム属性です。...

Vue の高度なコンポーネント機能コンポーネントの使用シナリオとソースコード分析

目次導入使用シナリオソースコード分析要約する導入Vue は、コンポーネントをステートレスかつインスタ...