--- title: JavaScript のデータ型とデータ構造 slug: Web/JavaScript/Data_structures tags: - Beginner - Guide - JavaScript - Types translation_of: Web/JavaScript/Data_structures ---
あらゆるプログラミング言語は、それぞれ異なったデータ構造を持っています。この記事では、JavaScript で使用可能な組み込みデータ構造の一覧と、他のデータ構造の構築にも使えるように、それらがどのような性質を持ち合わせているかについて述べることにします。また可能である場合は、他のプログラミング言語におけるデータ構造との対比も行います。
JavaScript は弱い型付けあるいは動的型付けの言語です。JavaScript では、変数が直接的に特定のデータ型に関連付けられているわけではなく、どの変数にもあらゆる型の値を代入(および再代入)できます。
let foo = 42; // foo は数値です foo = 'bar'; // foo は文字列です foo = true; // foo は真偽値です
最新の ECMAScript 標準では、次の 9 つの型が定義されています。
typeof instance === "object"
データではありませんが、構築された任意のオブジェクトインスタンスのための特別な構造型で、データ構造としても使用されます。new {{jsxref("Object")}}, new {{jsxref("Array")}}, new {{jsxref("Map")}}, new {{jsxref("Set")}}, new {{jsxref("WeakMap")}}, new {{jsxref("WeakSet")}}, new {{jsxref("Date")}} など new キーワードで作成されたほぼすべてのもの。typeof
演算子:typeof instance === "function"
に応答します。すべての関数コンストラクターはオブジェクトコンストラクターから派生していますが、これは単に Functions の特別な省略形にすぎません。typeof
演算子は、データ型以外を正しく判定できないので注意してください。オブジェクトから派生した構造的な型を判定しても、常に "object"
を受け取ることになるので、typeof
を使用する意味がありません。オブジェクトの型を確認するための適切な方法は、{{jsxref("Operators/instanceof", "instanceof")}} キーワードを使用することです。しかし、その場合でも誤った判定があるかもしれません。
ご覧のとおり、すべてのプリミティブ型の意味は、ほとんど同じである undefined と null を除いては明らかです。undefined は、まだ存在しない、あるいはもう存在しないものを表現します。null は、存在するが中身が空であることを表現したものです。
オブジェクトを除くすべての型は不変の値 (つまり、変更できない値) として定義されています。例えば文字列は(C 言語とは異なり)不変です。これらの型の値を、プリミティブ値と呼びます。
Boolean は論理的な実体であり true
と false
の 2 つの値があります。詳しくは Boolean および {{jsxref("Boolean")}} 参照してください。
Null 型は値が null
の 1 つしかありません。詳しくは {{jsxref("null")}} および Null を参照してください。
値を代入していない変数の値は undefined
になります。詳しくは {{jsxref("undefined")}} および Undefined を参照してください。
ECMAScript には、Number と BigInt の 2 つの組み込み数値型があります。(以下を参照)
Number 型は、IEEE 754 での倍精度浮動小数点数 ( -(253 − 1) から 253 − 1) の間の数値) です。浮動小数点数の表現に加えて、3 つの記号的な値 +Infinity
, -Infinity
, {{jsxref("NaN")}} ("Not a Number") があります。
{{jsxref("Infinity", "±Infinity")}} 内で使用可能な最大値または最小値を確認するには、定数 {{jsxref("Number.MAX_VALUE")}} または {{jsxref("Number.MIN_VALUE")}} を使用できます。
ECMAScript 2015 からは、{{jsxref("Number.isSafeInteger()")}}, {{jsxref("Number.MAX_SAFE_INTEGER")}}, {{jsxref("Number.MIN_SAFE_INTEGER")}} を使用して、数値が倍精度浮動小数点数の範囲内にあるかどうかを確認することができるようになりました。
この範囲を超えた JavaScript の整数値はもう正確ではなくなり、倍精度浮動小数点の近似値に丸められます。
Number 型には、2 種類の表現を持つ数値がひとつだけあります。それは 0
であり、-0
および +0
で表します。(0
は +0
の別名です)
実用上、どちらを使用しても影響はほとんどありません。例えば、+0 === -0
は true
です。ただし、ゼロ除算を行った場合は違いに気づくでしょう。
> 42 / +0 Infinity > 42 / -0 -Infinity
多くの場合、数値はその値のみを表しますが、JavaScript には{{jsxref("Operators/Bitwise_Operators", "バイナリー(ビット単位)演算子")}}も用意されています。
注: ビット演算子を使用すれば、ビットマスクを用いて、1 つの数値で複数の真偽値を表現することも可能です。しかしながら、JavaScript が(真偽値の配列や名前付きプロパティに真偽値が割り当てられたオブジェクトのような)真偽値の集合を表現する手段を提供しているため、この行いは悪い習慣として考えられます。ビットマスクはコードの可読性、わかりやすさ、保守性を大きく損なってしまいます。
ローカルストレージの容量的制約への対処や、ビット単位での転送量を考える必要のある極限状態など、非常に特殊なケースにおいてはこうしたテクニックが必要となるでしょう。このテクニックは、あくまでも最適化が必要な場合の最終手段としてのみ考慮すべきです。
{{jsxref("BigInt")}} 型は、任意の精度で整数を表現できる JavaScript の数値プリミティブです。BigInt
を使えば、Number
で扱える安全な整数の限界を超える、大きな整数を安全に格納して操作することができます。
BigInt
は、整数の末尾に n
を追加するか、コンストラクターを呼び出すことで作成します。
定数 {{jsxref("Number.MAX_SAFE_INTEGER")}} を使用することで、Number
でインクリメントできる最も安全な値を得ることができます。BigInt
の導入により、{{jsxref("Number.MAX_SAFE_INTEGER")}} を超える数値での操作が可能になりました。
この例は、{{jsxref("Number.MAX_SAFE_INTEGER")}} をインクリメントすると期待される結果が返ってくることを示しています。
> const x = 2n ** 53n; 9007199254740992n > const y = x + 1n; 9007199254740993n
BigInt
は、Number
と同じように +
, *
, -
, **
, %
演算子を使用できます。BigInt
は Number
と厳密に等しいわけではありませんが、ほとんど同じです。
BigInt
は、if
, ||
, &&
, Boolean
, !
などで真偽値
に変換される場合、Number と同じように動作します。
BigInt
は、Number
と同時に使用することはできません。代わりに、{{jsxref("TypeError")}} が投げられます。
JavaScript の {{jsxref("String")}} 型は、テキストデータを表すために使用します。これは、16 ビット符号なし整数値の「要素」の集合体で、文字列内の各要素は文字列内の位置を占めます。要素の数が文字列の長さになり、最初の要素がインデックス 0
、次の要素がインデックス 1
となっていきます。
いくつかのプログラミング言語(C 言語など)とは異なり、JavaScript の文字列は不変です。これは、一度作成した文字列を変更することができないことを意味します。
しかしながら、原文の文字列に対する操作に基づいて別の文字列を作成することは可能です。例えば、以下のようになります。
+
) または {{jsxref("String.concat()")}} を用いて、2 つの文字列を連結する複雑なデータを表現するために文字列を使用したい思うこともあるでしょう。これには短期的なメリットがあります。
XMLHttpRequest
の responseText
など)において共通分母であり、文字列だけで作業したいという誘惑に駆られることがあります。ルールさえあれば、どのようなデータ構造でも文字列で表現することが可能ですが、これは良いアイデアとは言えません。例えば、区切り文字を使用することでリストを模倣することができますが(JavaScript の配列の方が適しています)、残念なことに区切り文字がリストの要素となってしまった場合、リストが壊れてしまいます。エスケープした文字を使用することでこの問題に対処することは可能ですが、そのルールをすべてに用意する必要がある上、不必要なメンテナンスの負担を生み出します。
文字列はテキストデータには向いていますが、複雑なデータを表す場合は文字列を解析し、適切な抽象化を用いる必要があります。
シンボルは一意で不変のプリミティブ値であり、オブジェクトのプロパティのキーとして使用することができます。いくつかのプログラミング言語では、"atoms" と呼ばれています。
詳しくは、Symbol および{{jsxref("Symbol" ,"シンボル")}}ラッパーオブジェクトを参照してください。
コンピューター科学において、オブジェクトは識別子によって参照可能なメモリー内の値です。
JavaScript では、オブジェクトはプロパティの集合として見ることができます。オブジェクトリテラル構文は、プロパティの初期化・追加・削除を行い、String 値または Symbol 値のいずれかのキー値を使用して識別します。プロパティの値は、他のオブジェクトを含むあらゆる型の値にすることができ、複雑なデータ構造を構築できます。
オブジェクトには、データプロパティとアクセサプロパティという特定の属性を持つ 2 種類のプロパティがあります。
注: 各プロパティに対応する属性は JavaScript エンジンによって内部的に使用されるので、直接アクセスすることはできません。そのため、属性は 1 つではなく 2 つの角括弧で表示されています。
詳しくは {{jsxref("Object.defineProperty()")}} を参照してください。
キーと値を関連づけて、以下の属性を持ちます。
属性 | 型 | 説明 | 既定値 |
---|---|---|---|
[[Value]] | JavaScript の任意の型 | プロパティにアクセスすると取り出される値です。 | undefined |
[[Writable]] | Boolean | false であれば、プロパティの [[Value]] は変更できません。 |
false |
[[Enumerable]] | Boolean |
If |
false |
[[Configurable]] | Boolean | false であれば、プロパティは削除できません。また、[[Value]] および [[Writable]] 以外の属性を変更できません。 |
false |
属性 | 型 | 説明 |
---|---|---|
Read-only | Boolean | ES5 の [[Writable]] 属性の状態を反転したもの。 |
DontEnum | Boolean | ES5 の [[Enumerable]] 属性の状態を反転したもの。 |
DontDelete | Boolean | ES5 の [[Configurable]] 属性の状態を反転したもの。 |
値を取り出しまたは保存するための 1 つまたは 2 つのアクセサ関数(get
および set
)とキーを関連づけており、以下の属性を持ちます。
属性 | 型 | 説明 | 既定値 |
---|---|---|---|
[[Get]] | Function オブジェクトまたは undefined |
値に対して get アクセスが実行されると、関数が引数なしで呼び出されてプロパティの値を取り出します。get も参照してください。 |
undefined |
[[Set]] | Function オブジェクトまたは undefined |
指定したプロパティを変更しようとしたときに、代入する値を引数に含めて関数が呼び出されます。set も参照してください。 |
undefined |
[[Enumerable]] | Boolean | true であれば、プロパティは for...in ループで列挙されます。 |
false |
[[Configurable]] | Boolean | false であれば、プロパティの削除やデータプロパティの変更はできません。 |
false |
JavaScript オブジェクトはキーと値を所持しています。キーは文字列(または{{jsxref("Symbol", "シンボル")}})ですが、値はなんでもかまいません。これにより、オブジェクトは HashMap に自然に適合します。
関数は呼び出し可能という付加機能を持つ、通常のオブジェクトです。
日付を表現する場合は、JavaScript に組み込まれた Date
ユーティリティ を使用するのが最適です。
配列は、整数値をキーにするプロパティと length
プロパティの間に特殊な関係の存在する、標準オブジェクトです。
さらに、配列は Array.prototype
を継承しており、配列を操作するための便利なメソッドを提供しています。例えば、indexOf
(配列中の値の検索)や push
(配列への要素の追加)などです。これにより、配列はリストや集合を表現するのに最適な候補となります。
型付き配列は、ECMAScript 2015 で JavaScript に新しく追加されたもので、基礎となるバイナリーデータバッファの配列状のビューを提示します。次の表は、同等の C データ型を見つけるのに役立ちます。
型 | 値の範囲 | サイズ (バイト数) | 説明 | Web IDL 型 | 同等の C 型 |
---|---|---|---|---|---|
{{jsxref("Int8Array")}} | -128 から 127 |
1 | 8 ビット 2 の補数方式の符号付き整数値 | byte |
int8_t |
{{jsxref("Uint8Array")}} | 0 から 255 |
1 | 8 ビット 符号なし整数値 | octet |
uint8_t |
{{jsxref("Uint8ClampedArray")}} | 0 から 255 |
1 | 8 ビット 符号なし整数値 (切り詰め) | octet |
uint8_t |
{{jsxref("Int16Array")}} | -32768 から 32767 |
2 | 16 ビット 2 の補数方式の符号付き整数値 | short |
int16_t |
{{jsxref("Uint16Array")}} | 0 から 65535 |
2 | 16 ビット 符号なし整数値 | unsigned short |
uint16_t |
{{jsxref("Int32Array")}} | -2147483648 から 2147483647 |
4 | 32 ビット 2 の補数方式の符号付き整数値 | long |
int32_t |
{{jsxref("Uint32Array")}} | 0 から 4294967295 |
4 | 32 ビット 符号なし整数値 | unsigned long |
uint32_t |
{{jsxref("Float32Array")}} | 1.2 ×10-38 から 3.4 ×1038 |
4 | 32 ビット IEEE 浮動小数点数 (7 桁の有効数字 例:1.1234567 ) |
unrestricted float |
float |
{{jsxref("Float64Array")}} | 5.0 ×10-324 から 1.8 ×10308 |
8 | 64 ビット IEEE 浮動小数点数 (16 桁の有効数字 例:1.123...15 ) |
unrestricted double |
double |
{{jsxref("BigInt64Array")}} | -263 から 263-1 |
8 | 64 ビット 2 の補数方式の符号付き整数値 | bigint |
int64_t (signed long long) |
{{jsxref("BigUint64Array")}} | 0 から 264-1 |
8 | 64 ビット 符号なし整数値 | bigint |
uint64_t (unsigned long long) |
ECMAScript 2015 で導入されたこれらのデータ構造は、オブジェクト参照をキーとしています。{{jsxref("Set")}} と {{jsxref("WeakSet")}} はオブジェクトの集合を表し、{{jsxref("Map")}} と {{jsxref("WeakMap")}} はオブジェクトに値を関連付けます。
Map
と WeakMap
の違いは、前者ではオブジェクトキーを列挙できることです。これにより、後者の場合にガベージコレクションの最適化が可能になります。
純粋な ECMAScript 5 で Map
と Set
を実装することもできますが、オブジェクトを比較することはできないので(例えば <
未満の意味で)、検索性能が必然的に線形になります。これらのネイティブ実装(WeakMap
を含む)は、一定時間に対してほぼ対数的な検索性能を持つことができます。
通常、DOM ノードにデータをバインドするには、オブジェクトに直接プロパティを設定するか、data-*
属性を使用します。これらの手法は同じコンテクストで実行されるあらゆるスクリプトからデータの利用が可能であるため、不都合な面を持ち合わせていました。Map
や WeakMap
を使うと、オブジェクトへのプライベートなデータバインドを簡単に行うことができます。
JSON (JavaScript Object Notation) は JavaScript から派生した汎用データ構造をもつ軽量なデータ交換フォーマットであり、多くのプログラミング言語で使用されています。
詳しくは JSON および {{jsxref("JSON")}} を参照してください。
JavaScript には組み込みオブジェクトの標準ライブラリがあります。
オブジェクトの詳細については、リファレンスを参照してください。
typeof
演算子を使用して型を検出するtypeof
演算子は、変数の型を知るのに役立ちます。
詳細および使用例については、リファレンスページを参照してください。
仕様書 |
---|
{{SpecName('ESDraft', '#sec-ecmascript-data-types-and-values', 'ECMAScript Data Types and Values')}} |