インデックス登録されたコレクション

インデックス付きコレクションは、番号付きインデックスを使用して要素が保存され、アクセスされるデータ構造です。インデックス付きコレクションに格納された値には、0 から始まる番号付きのインデックスが割り当てられます。これは「ゼロ インデックス」というパターンです。その後、インデックスを参照することで、インデックス付きコレクションに格納されている値にアクセスできます。

配列

配列は、任意のデータ型(複雑なオブジェクトや他の配列など)の 0 個以上の値を保持できるコンテナです。配列に格納された値は、配列の「要素」と呼ばれることもあります。

配列を作成する

プリミティブ データ型と同様に、配列を作成するには 2 つの方法があります。配列リテラルとして作成する方法と、new Array() を指定して JavaScript の組み込み Array() コンストラクタを呼び出す方法です。配列を変数に割り当てると、1 つの識別子に複数の値を割り当てる、移植性が高く反復可能な方法を使用できます。

配列リテラルの構文では、0 個以上のカンマ区切りデータ値をかっこ([])で囲みます。

const myArray = [];

配列コンストラクタ構文では、new キーワードを指定したコンストラクタとして JavaScript の組み込み Array オブジェクトを使用します。

const myArray = new Array();

配列リテラルの構文と配列コンストラクタの構文のどちらでも、配列の作成時に情報を代入できます。ただし、値の定義方法は構文が若干異なります。配列リテラルの構文では、かっこ内にカンマ区切り値を使用します。これは、結果の配列と同じように見えます。

const myArray = [ true, null, "String", false ];

myArray;
> [ true, null, "String", false ]

配列コンストラクタの構文は、カンマ区切りの値を引数として受け取りますが、特別な動作例外が 1 つあります。

const myArray = new Array( true, null, "String", false );

myArray;
> Array(4) [ true, null, "String", false ]

単一の数値値が Array コンストラクタに渡されると、その値は結果の配列の 0 番目の位置に割り当てられません。代わりに、配列は値用のその数の空のスロットで作成されます。配列に制限は課されません。配列リテラルの場合と同じ方法で、アイテムの追加と削除を行うことができます。

// Firefox:\
const myArray = new Array( 10 );

myArray;
> Array(10) [ <10 empty slots> ]
// Chrome:
const myArray = new Array( 10 );

myArray;
> (10) [empty × 10]

空のスロットを含む配列(「スパース配列」とも呼ばれます)は特殊なケースです。空のスロットは、undefined または明示的に null の値を含むのではなく、多くの場合、言語の他の場所で undefined 値として処理されますが、常にそうではありません。

配列リテラルを作成するときにカンマの間に値を省略すると、配列リテラル構文を使用してスパース配列を誤って作成してしまう可能性があります。

const myArray = [ true,, true, false ];

myArray;
> Array(4) [ true, <1 empty slot>, true, false ]

空のスロットは、すべてのコンテキストで意味のある値として扱われるわけではありませんが、配列の全長に考慮されるため、配列の値を反復処理するときに予期しない結果が生じる可能性があります。

const myArray = [ 1,, 3, 4 ];

myArray.length;
> 4

for( const myValue of myArray ) {
  console.log( myValue + 10 );
}
> 11
> NaN
> 13
> 14

この動作は、JavaScript の初期の設計上の決定事項から引き継いだものです。最新の開発ではスパース配列を使用しないでください。

プリミティブと同様に、配列リテラルは対応するコンストラクタからプロパティとメソッドを継承します。配列は特別な形式のオブジェクトであるため、配列リテラルの構文と new Array() 構文によって機能的に同じ結果(Array コンストラクタからプロトタイプを継承するオブジェクト)が生成されます。

const arrayLiteral = [];
const arrayConstructor = new Array();

typeof arrayLiteral;
> "object"

arrayLiteral;
> Array []
    length: 0
    <prototype>: Array []

typeof arrayConstructor;
> "object"

arrayConstructor;
> Array []
    length: 0
    <prototype>: Array []

2 つの結果は同一で、配列リテラルの構文はより簡潔でリテラルであるため、new Array() 構文ではなく配列リテラルの構文を常に使用することを強くおすすめします。

配列値にアクセスする

配列内の個々の要素にアクセスするには、角かっこ([])を配列または識別子の後に配置し、その要素のインデックスを参照する番号を使用します。


[ "My string", "My other string" ][ 1 ];
> "My other string"

const myArray = [ "My string", 50, true ];

myArray[ 0 ];
> "My string"

myArray[ 1 ];
> 50

myArray[ 2 ];
> true

JavaScript の配列は結合的ではありません。つまり、任意の文字列をインデックスとして使用することはできません。ただし、配列内の要素にアクセスするために使用される数値は、バックグラウンドで文字列値に強制変換されます。つまり、数字のみを含む文字列値を使用できます。

const myArray = [ "My string", 50, true ];

myArray[ 2 ];
> true

myArray[ "2" ];
> true

配列で定義されている要素外の要素にアクセスしようとすると、エラーではなく undefined が発生します。

const myArray = [ "My string", 50, true ];

myArray[ 9 ];
> undefined

割り当ての分解

分離割り当ては、配列またはオブジェクトから値の範囲を抽出し、それを一連の識別子に割り当てる簡潔な方法です。このプロセスは、元の配列またはオブジェクトを変更することはありませんが、元のデータ構造の「展開」とも呼ばれます。

分離割り当てでは、識別子の配列またはオブジェクトのようなリストを使用して、値を追跡します。バインディング パターンの分解と呼ばれる最も単純な形式で、各値は配列またはオブジェクトから展開され、対応する変数に代入され、let または const(または var)で初期化されます。

const myArray = [ "A string", "A second string" ];
const [ myFirstElement, mySecondElement ] = myArray;

const myObject = { firstValue: false, secondValue: true };
const { myProp, mySecondProp } = myObject;

myFirstElement;
> "My string"

mySecondElement;
> "Second string"

myProp;
> false

mySecondProp;
> true

オブジェクトを分離するには中かっこ({})を使用し、配列を分離するには角かっこ([])を使用します。

const myArray = [ false, true ];
const myObject = { firstValue: false, secondValue: true };

const [ myProp, mySecondProp ] = myObject;
> Uncaught TypeError: myObject is not iterable

const { myElement, mySecondElement } = myArray;

myElement
> undefined

mySecondElement;
> undefined

配列の分解は、左から右の順番で行われます。分離割り当ての各識別子は、同じインデックスを持つ配列の要素に対応しています。

const myArray = [ 1, 2, 3 ];
const [ myElement, mySecondElement, myThirdElement ] = myArray;

myElement;
> 1

mySecondElement;
> 2

myThirdElement;
> 3

これは、オブジェクトを分解するときのデフォルトの動作でもあります。ただし、分離割り当てで使用される識別子がオブジェクトのプロパティのキーと一致する場合、それらの識別子には、指定された順序に関係なく、対応するプロパティ値が入力されます。

const myObject = { firstValue: 1, secondValue: 2, thirdValue 3 };
const { secondValue, thirdValue, firstValue } = myObject;

firstValue;
> 1

secondValue;
> 2

thirdValue;
> 3

要素をスキップするには、識別子を省略します。

const myArray = [ 1, 2, 3 ];
const [ firstValue,, secondValue ] = myArray;

firstValue;
> 1

secondValue;
> 3

分離構文を使用すると、分離された値が空のスロット(スパース配列の場合など)または undefined 値である場合に、デフォルト値を割り当てることもできます。

const myArray = [ true, ];
const [ firstValue = "Default string.", secondValue = "Default string." ] = myArray;

firstValue;
> true

secondValue;
> "Default string."

分解によって値が特定の型に強制変換されることはありません。つまり、空の文字列("")や null などの「誤った」値も、意味のある分解された値とみなされます。

const myArray = [ false, null, 0, "",, undefined ];
const [ falseValue = true, nullValue = true, zeroValue = true, emptyStringValue = true, emptySlot = true, undefinedValue = true ] = myArray;

falseValue;
> false;

nullValue;
> null

zeroValue;
> 0

emptyStringValue;
> ""

emptySlot;
> true

undefinedValue;
> true

スプレッド オペレーター

配列、文字列、オブジェクト リテラルなどの反復可能なデータ構造を個々の要素に拡張するには、ES6 で導入されたスプレッド演算子(...)を使用します。スプレッド演算子の直後に、展開するデータ構造、またはそのデータ構造を含む変数の識別子が続きます。

const myArray = [ 1, 2, 3 ];

console.log( ...myArray );
> 1 2 3

スプレッド構文は、主に配列のコピーと結合に使用されます。

const myArray = [ 4, 5, 6 ];
const mySecondArray = [1, 2, 3, ...myArray ];

mySecondArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

スプレッド構文は、次のコンテキストでのみ使用できます。

配列と文字列の場合、スプレッド構文は、関数呼び出し内の 0 個以上の引数または配列内の要素が想定される場合にのみ適用されます。このセクションの分散演算子の構文の最初の例は、組み込みの console.log メソッドに引数として ...myArray を渡すため、機能します。

たとえば、分散するデータを別の配列の外部の変数に割り当てることはできません。

const myArray = [ 1, 2, 3 ];
const spreadVariable = ...myArray;
> Uncaught SyntaxError: Unexpected token '...'

ただし、元の配列を配列リテラルに広げることで配列をコピーします。

const myArray = [ 1, 2, 3 ];
const spreadArray = [ ...myArray ];

spreadArray;
> Array(3) [ 1, 2, 3 ]

2 つ以上の配列を構成する要素を 1 つの配列に結合するには:

const myArray = [ 1, 2, 3 ];
const mySecondArray = [ 4, 5, 6 ];
const myNewArray = [ ...myArray, ...mySecondArray ];

myNewArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

または、関数呼び出しで配列の要素を個別の引数として渡すこともできます。

const myArray = [ true, false ];
const myFunction = ( myArgument, mySecondArgument ) => {
    console.log( myArgument, mySecondArgument );
};

myFunction( ...myArray );
> true false

スプレッド演算子は、ES2018 のオブジェクト リテラルで動作するように拡張されました。配列と同様に、スプレッド演算子を使用してオブジェクトを複製または結合できます。

const myObj = { myProperty : true };
const mySecondObj = { ...myObj };

mySecondObj;
> Object { myProperty: true }
const myFirstObj = { myProperty : true };
const mySecondObj = { additionalProperty : true };
const myMergedObj = { ...myFirstObj, ...mySecondObj };

myMergedObj;
> Object { myProperty: true, additionalProperty: true }

スプレッド演算子は「シャロー」コピーを作成します。つまり、元のオブジェクトのプロトタイプと列挙不可能なプロパティはコピーされません。

const myCustomPrototype = { protoProp: "My prototype." };
const myObj = Object.create( myCustomPrototype, {
    myEnumerableProp: {
        value: true,
        enumerable: true
    },
    myNonEnumerableProp: {
        value: false,
        enumerable: false
    }
});
const myNewObj = { ...myObj };

myObj;
> Object { myEnumerableProp: true, … }
    myEnumerableProp: true
    myNonEnumerableProp: false
    <prototype>: Object { protoProp: "My prototype." }

myNewObj;
> Object { myEnumerableProp: true }
    myEnumerableProp: true
    <prototype>: Object { … }

配列とオブジェクトは同じ意味で使用することはできません。オブジェクトを配列に、または配列をオブジェクトにスプレッドすることはできません。

REST オペレーター

演算子自体の構文は同じですが、REST 演算子(...)は、使用されているコンテキストに基づいて反対の関数を実行します。分解割り当て関数パラメータの場合のように、イテラブル データ構造を個々の要素に展開するのではなく、レスト演算子が要素を結合してイテラブル データ構造にします。この名前の由来は、一連のデータ値の「残り」を収集するためです。

分割割り当てで使用する場合、この構文は「REST プロパティ」構文と呼ばれます。

const myArray = [ "First", "Second", "Third", "Fourth", "Fifth" ];

[ myFirstElement, mySecondElement, ...remainingElements ] = myArray;

myFirstElement;
> "First"

mySecondElement;
> "Second"

remainingElements;
> Array(3) [ "Third", "Fourth", "Fifth"]

関数に無制限の引数を渡すために使用される構文は、「rest parameter」構文と呼ばれます。

function myFunction( ...myParameters ) {
    let result = 0;
    myParameters.forEach( ( myParam ) => {
        result += myParam;
    });
    return result;
};

myFunction( 2, 2 );
> 4

myFunction( 1, 1, 1, 10, 5 );
> 18

myFunction( 10, 11, 25 );
> 46

%TypedArray%

型付き配列は、アップロードされたファイルや WebGL を操作する場合などに、構造化されたバイナリデータを格納するように設計された ES6 機能です。

シンボルと同様に、%TypedArray% 組み込み関数(通常は %TypedArray% または @@TypedArray として記載されるため、グローバル プロパティと間違われない)は従来の意味ではコンストラクタ関数ではなく、new で呼び出すことも、直接呼び出すこともできません。代わりに、%TypedArray% は個々のコンストラクタの親スーパークラスを参照します。各コンストラクタは、特定のバイナリデータ形式に対応しています。組み込みの %TypedArray% スーパークラスには、すべての %TypedArray% コンストラクタ サブクラスとそのインスタンスが継承するプロパティとユーティリティ メソッドが用意されています。

理解度をチェックする

「const myArray = [ 30, 50, 70 ];」の場合、「myArray[1]」は何を返しますか。

50
30
70

「myArray」に 3 つの値がある場合、「myArray[9]」は何を返しますか。

Undefined
エラー メッセージが表示される
9
Null