Indexed collections

by 1 contributor:

This article is in need of an editorial review.

This translation is incomplete. Please help translate this article from English.

この章では、インデックス値により順序付けされたデータのコレクションを紹介します。これは配列やArrayオブジェクトやTypedArrayオブジェクトのような配列のコンストラクタを含みます。

Array オブジェクト

arrayは名前やインデックスで参照する値の順序付けされた集合です。例えば、従業員番号によってインデックスされ、従業員の名前を含むempと呼ばれる配列があります。だから、emp[1]は従業員番号1です。emp[2]は従業員番号2、・・・・となります。

JavaScriptは明白な配列データ型を持ちません。しかしながら、アプリケーションで配列として動作する定義済のArrayオブジェクトとメソッドを使用できます。Arrayオブジェクトは、接合、反転、ソートのような様々な方法で複数の配列に対してメソッドを持ちます。配列の長さを判断するプロパティや正規表現で使用するための他のプロパティを持ちます。

配列を生成する

次のステートメントでは、同等の配列を作成します:

var arr = new Array(element0, element1, ..., elementN);
var arr = Array(element0, element1, ..., elementN);
var arr = [element0, element1, ..., elementN];

element0, element1, ..., elementNは配列の要素の値のリストです。これらの値が指定されるとき、配列は、配列の要素として初期化されます。配列のlengthプロパティは引数の数に設定されます。

ブラケットの構文は"array literal" または "array initializer."と呼ばれます。これは、配列の作成の他の形態よりも短いです。だから、一般的に好ましいです。詳細について、Array literalsをご覧ください。

ゼロ出ない長さの配列を生成するが、アイテムなしで生成するために、次の内どちらかが使用されます。:

var arr = new Array(arrayLength);
var arr = Array(arrayLength);

// This has exactly the same effect
var arr = [];
arr.length = arrayLength;

注意: 上記のコードで、arrayLengthNumberである必要があります。さもなければ、単一の要素(提供される値)を持つ配列が生成されます。arr.lengthを呼ぶとarrayLengthが返されます。しかし、配列は実際は空の(undefined)要素を含みます。配列上でfor...inループを実行すると配列要素が帰りません。

上記で示されるように新しく定義された変数に加えて、配列は新しい、または、既存のオブジェクトのプロパティとして割り当てられます。:

var obj = {};
// ...
obj.prop = [element0, element1, ..., elementN];

// OR
var obj = {prop: [element0, element1, ...., elementN]}

単一の要素で配列を初期化して要素がNumberになる場合、ブラケットの構文を使用する必要があります。単一のNumber値がArray()コンストラクタか関数に渡されるとき、単一の要素としてではなく、arrayLengthとして解釈されます。

var arr = [42];
var arr = Array(42); // Creates an array with no element, 
                     // but with arr.length set to 42

// The above code is equivalent to
var arr = [];
arr.length = 42;

Nが、小数部分が非ゼロの非整数である場合、Array(N) を呼ぶと、結果はRangeErrorになります。次の例では、この動作を示しています。

var arr = Array(9.3);  // RangeError: Invalid array length

任意のデータ型の単一の要素を持つ配列を作成する必要がある場合は、配列リテラルを使用する方が安全です。さもなければ、単一の要素を追加する前に、最初に空の配列を作成します。

配列の移入

あなたは、その要素に値を割り当てることによって、配列を作成することができます。例えば、

var emp = [];
emp[0] = "Casey Jones";
emp[1] = "Phil Lesh";
emp[2] = "August West";

注意: あなたは上記のコードでは配列演算子に非整数値を指定する場合、プロパティは配列要素ではなく配列を表すオブジェクト内に作成されます。

var arr = [];
arr[3.4] = "Oranges";
console.log(arr.length);                // 0
console.log(arr.hasOwnProperty(3.4));   // true

配列を作成するときにも、配列を取り込むことができます。:

var myArray = new Array("Hello", myVar, 3.14159);
var myArray = ["Mango", "Apple", "Orange"]

配列要素を参照する

要素の序数を用いて配列の要素を参照してください。例えば、次の配列を定義すると仮定します。:

var myArray = ["Wind", "Rain", "Fire"];

myArray[0]として配列の最初の要素に参照し、myArray[1]として配列の二番目の要素を参照します。要素のインデックスはゼロから始まります。

注意: 配列演算子(角括弧)もまた配列のプロパティにアクセスするために使用されます(配列はJavaScript内でオブジェクトです)。例えば、

var arr = ["one", "two", "three"];
arr[2];  // three
arr["length"];  // 3

長さを理解する

実装のレベルで、JavaScript'の配列は、プロパティ名として配列のインデックスを使用して、標準のオブジェクトプロパティとして要素を実際に格納します。lengthプロパティは特別です。すなわち、常に最終要素のインデックス+1を返します(次の例では、Dustyは30でインデックスされています。だから、cats.lengthは30 + 1を返します)。 忘れないでください、JavaScript Array インデックスは0系です。すなわち、1からではなく、0から始まります。これは、lengthプロパティは配列に格納されている最高のインデックス値より1つ上の値になることを意味します。:

var cats = [];
cats[30] = ['Dusty'];
console.log(cats.length); // 31

lengthプロパティに割り当てることができます。格納されているアイテムの数より小さい値を設定すると、配列は切り捨てられます。すなわち、0に設定すると完全に配列を空にします。:

var cats = ['Dusty', 'Misty', 'Twiggy'];
console.log(cats.length); // 3

cats.length = 2;
console.log(cats); // logs "Dusty,Misty" - Twiggy has been removed

cats.length = 0;
console.log(cats); // logs nothing; the cats array is empty

cats.length = 3;
console.log(cats); // [undefined, undefined, undefined]

配列を反復処理

一般的な操作は、いくつかの方法で、それぞれを処理する、配列の値を繰り返し処理することです。これを行う最も簡単な方法は次のとおりです。:

var colors = ['red', 'green', 'blue'];
for (var i = 0; i < colors.length; i++) {
  console.log(colors[i]);
}

配列内の要素のいずれも真偽値falseに評価さないことがわかっている場合、すなわち、配列がDOMノードのみで構成されている場合、例えば、より効率的なイディオムを使用することができます。:

var divs = document.getElementsByTagName('div');
for (var i = 0, div; div = divs[i]; i++) {
  /* Process div in some way */
}

これは、配列の長さをチェックするオーバーヘッドを回避します。そして、div変数が利便のためにループの現在のアイテムに毎回再割当てされることを保証します。

forEach()メソッドは配列を反復する別の方法を提供します。:

var colors = ['red', 'green', 'blue'];
colors.forEach(function(color) {
  console.log(color);
});

forEachに渡される関数は、その関数への引数として渡される配列の要素とともに、配列内の各アイテムごとに一回実行されます。割り当てられていない値はforEachループで反復されません。

配列が定義されているとき省略されている配列の要素が、forEach,によって反復するとき表示されません。しかし、undefinedが手動で要素に割り当てられているとき表示されます。:

var array = ['first', 'second', , 'fourth'];

// returns ['first', 'second', 'fourth'];
array.forEach(function(element) {
  console.log(element);
})

if(array[2] === undefined) { console.log('array[2] is undefined'); } // true

var array = ['first', 'second', undefined, 'fourth'];

// returns ['first', 'second', undefined, 'fourth'];
array.forEach(function(element) {
  console.log(element);
})

JavaScriptの要素は標準オブジェクトプロパティとして保存されるので、for...inループを使用してJavaScript配列を反復することはお勧めできません。というのも、通常の要素とすべての列挙プロパティは表示されるからです。

配列メソッド

Arrayオブジェクトは次のメソッドを持ちます。:

concat()は2つの配列を結合し、新しい配列を返します。

var myArray = new Array("1", "2", "3");
myArray = myArray.concat("a", "b", "c"); 
// myArray is now ["1", "2", "3", "a", "b", "c"]

join(deliminator = ',')は配列のすべての要素を文字列に結合します。

var myArray = new Array("Wind", "Rain", "Fire");
var list = myArray.join(" - "); // list is "Wind - Rain - Fire"

push()は一つ以上の要素を配列の最後に追加し、配列の得られた長さを返します。

var myArray = new Array("1", "2");
myArray.push("3"); // myArray is now ["1", "2", "3"]

pop()は配列から最後の要素を取り除き、その要素を返します。

var myArray = new Array("1", "2", "3");
var last = myArray.pop(); 
// myArray is now ["1", "2"], last = "3"

shift()は配列から最初の要素を取り除き、その要素を返します。

var myArray = new Array ("1", "2", "3");
var first = myArray.shift(); 
// myArray is now ["2", "3"], first is "1"

unshift()は一つ以上の要素を配列の先頭に追加し、配列の新しい長さを返します。

var myArray = new Array ("1", "2", "3");
myArray.unshift("4", "5"); 
// myArray becomes ["4", "5", "1", "2", "3"]

slice(start_index, upto_index) は配列の一部を抽出し、新しい配列を返します。

var myArray = new Array ("a", "b", "c", "d", "e");
myArray = myArray.slice(1, 4); // starts at index 1 and extracts all elements
                               // until index 3, returning [ "b", "c", "d"]

splice(index, count_to_remove, addElement1, addElement2, ...)は要素を配列から取り除き、(必要に応じて)置き換えます。

var myArray = new Array ("1", "2", "3", "4", "5");
myArray.splice(1, 3, "a", "b", "c", "d"); 
// myArray is now ["1", "a", "b", "c", "d", "5"]
// This code started at index one (or where the "2" was), 
// removed 3 elements there, and then inserted all consecutive
// elements in its place.

reverse()は配列の要素を転置します。: 最初の配列要素は最後になり、最後の配列要素は最初になります。

var myArray = new Array ("1", "2", "3");
myArray.reverse(); 
// transposes the array so that myArray = [ "3", "2", "1" ]

sort()は配列要素をソートします。

var myArray = new Array("Wind", "Rain", "Fire");
myArray.sort(); 
// sorts the array so that myArray = [ "Fire", "Rain", "Wind" ]

sort()は、配列要素がどのように比較されるか判断するためにcallback関数も受け取ります。その関数は二つの値を比較し、三つの値のうち一つを返します。:

例えば、次では、文字列の最後の文字によってソートします。:

var sortFn = function(a, b){
  if (a[a.length - 1] < b[b.length - 1]) return -1;
  if (a[a.length - 1] > b[b.length - 1]) return 1;
  if (a[a.length - 1] == b[b.length - 1]) return 0;
}
myArray.sort(sortFn); 
// sorts the array so that myArray = ["Wind","Fire","Rain"]
  • aがソートシステムによってbより小さい場合、-1 (または、任意の負の数)を返します。
  • aがソートシステムによってbより大きい場合1 (または、任意の正の数)を返します。
  • abが等価とかんがえられる場合、0を返します。

indexOf(searchElement[, fromIndex])searchElementを見つけようとして配列を検索します。そして、最初に一致した位置のインデックスを返します。

var a = ['a', 'b', 'a', 'b', 'a'];
console.log(a.indexOf('b')); // logs 1
// Now try again, starting from after the last match
console.log(a.indexOf('b', 2)); // logs 3
console.log(a.indexOf('z')); // logs -1, because 'z' was not found

lastIndexOf(searchElement[, fromIndex])indexOfのように動作します。しかし、最後から開始して後方に検索します。

var a = ['a', 'b', 'c', 'd', 'a', 'b'];
console.log(a.lastIndexOf('b')); // logs 5
// Now try again, starting from before the last match
console.log(a.lastIndexOf('b', 4)); // logs 1
console.log(a.lastIndexOf('z')); // logs -1

forEach(callback[, thisObject]) はすべての配列アイテムごとにcallbackを実行します。

var a = ['a', 'b', 'c'];
a.forEach(function(element) { console.log(element);} ); 
// logs each item in turn

map(callback[, thisObject])はすべての配列アイテムごとにcallbackを実行した戻り値の新しい配列を返します。

var a1 = ['a', 'b', 'c'];
var a2 = a1.map(function(item) { return item.toUpperCase(); });
console.log(a2); // logs A,B,C

filter(callback[, thisObject]) はcallbackがtrueを返すアイテムを含む新しい配列を返します。

var a1 = ['a', 10, 'b', 20, 'c', 30];
var a2 = a1.filter(function(item) { return typeof item == 'number'; });
console.log(a2); // logs 10,20,30

every(callback[, thisObject])callbackが配列内のアイテムごとにtrueを返す場合trueを返します。

function isNumber(value){
  return typeof value == 'number';
}
var a1 = [1, 2, 3];
console.log(a1.every(isNumber)); // logs true
var a2 = [1, '2', 3];
console.log(a2.every(isNumber)); // logs false

some(callback[, thisObject])callbackが配列内の少なくとも一つのアイテムがtrueを返す場合trueを返します。

function isNumber(value){
  return typeof value == 'number';
}
var a1 = [1, 2, 3];
console.log(a1.some(isNumber)); // logs true
var a2 = [1, '2', 3];
console.log(a2.some(isNumber)); // logs true
var a3 = ['1', '2', '3'];
console.log(a3.some(isNumber)); // logs false

callback関数を受け取る上記のメソッドはiterative methodsとして知られています。というのも、いくつかの方法で配列全体を反復するからです。各アイテムはthisObjectと呼ばれる必要に応じた第二引数を受け取ります。与えられた場合、thisObjectはcallback関数の本体内でthisキーワードの値になります。与えられない場合、関数が明示的にオブジェクトコンテキストの外側で呼び出される他の場合と同様、thisはグローバルオブジェクト(window)を参照します。

callback関数は実際に三つの引数で呼ばれます。第一引数は現在のアイテムの値、第二引数は配列のインデックス、 第三引数は配列自身への参照です。JavaScript 関数はパラメータリストで指定されていないどんな引数でも無視します。だから、alertのような単一の引数のみを受け取るcallback関数を提供するのは安全です。

reduce(callback[, initialValue]) は単一の値にアイテムのリストを低減するためにcallback(firstValue, secondValue)を適用します。

var a = [10, 20, 30];
var total = a.reduce(function(first, second) { return first + second; }, 0);
console.log(total) // Prints 60

reduceRight(callback[, initalvalue])reduce()のように動作します。しかし最後の要素から開始します。

reducereduceRight は反復配列のメソッドのうち少なくとも明らかです。単一の値と配列を低減するために、再帰的に2つの値を組み合わせたアルゴリズムを使用する必要があります。

多次元配列

Arraysはネストできます。これは配列が要素として配列を含むことができることを意味します。JavaScriptの配列の特徴を使用して多次元配列が生成されます。

次のコードは2次元配列を作成します。

var a = new Array(4);
for (i = 0; i < 4; i++) {
  a[i] = new Array(4);
  for (j = 0; j < 4; j++) {
    a[i][j] = "[" + i + "," + j + "]";
  }
}

この例では、次の行を持つ配列を作成します:

Row 0: [0,0] [0,1] [0,2] [0,3]
Row 1: [1,0] [1,1] [1,2] [1,3]
Row 2: [2,0] [2,1] [2,2] [2,3]
Row 3: [3,0] [3,1] [3,2] [3,3]

配列と正規表現

配列が正規表現と文字列の間のマッチの結果である場合には、配列は、プロパティと一致についての情報を提供する要素を返します。配列はRegExp.exec()String.match()String.split()の戻り値です。正規表現とともに配列を使用する情報についてRegular Expressionsをご覧ください。

配列オブジェクトとともに動作する

document.getElementsByTagName()によって返されるNodeListか関数本体内で利用可能であるargumentsオブジェクトのように、いくつかのJavaScriptオブジェクトは、表面上の配列のように見えて振る舞いますが、それらのメソッドのすべてを共有することはありません。例えば、arguments オブジェクトはlength属性を提供しますが、forEach()メソッドを実装しません。

アレイジェネリックは、他の配列オブジェクトに反して、Arrayメソッドを実行する方法を提供します。各標準配列メソッドはArrayオブジェクト自身上で一致するメソッドを持ちます。例えば、:

function printArguments() {
  Array.forEach(arguments, function(item) {
    console.log(item);
  });
}

これらのジェレリックメソッドはJavaScript関数オブジェクトによって提供される呼び出しメソッドを使用してJavaScriptの旧バージョンでくどくどとエミュレートされます。:

Array.prototype.forEach.call(arguments, function(item) {
  console.log(item);
});

アレイジェネリックメソッドはstring上でも同様に使用されます。というのも、配列と同じ方法で文字への連続したアクセスを提供するからです。:

Array.forEach("a string", function(chr) {
  console.log(chr);
});

配列の内包表記

JavaScript 1.7で導入され、ECMAScript 7で標準化されるように提案されました。 array comprehensionsは別の内容に基づいた新しい配列を構築する便利なショートカットを提供します。内包表記はmap()filter()や二つを組み合わせた方法としてしばしば使用されます。

次の内包表記は数値の配列を受け取り各数値のdouble型の新しい配列を生成します。

var numbers = [1, 2, 3, 4];
var doubled = [i * 2 for (i of numbers)];
console.log(doubled); // logs 2,4,6,8

これは、次のmap()操作と同等です。:

var doubled = numbers.map(function(i){return i * 2;});

内包表記は特定の式と一致するアイテムを選択するために使用されます。ここでは偶数のみを選択する内包表記です。:

var numbers = [1, 2, 3, 21, 22, 30];
var evens = [i for (i of numbers) if (i % 2 === 0)];
console.log(evens); // logs 2,22,30

filter()は同じ目的のために使用されます。:

var evens = numbers.filter(function(i){return i % 2 === 0;});

map()スタイル操作 と filter()スタイル操作は単一の配列内包表記に組み合わせることができます。ここでは偶数だけをフィルタする内包表記で、double型を含む配列を生成します。:

var numbers = [1, 2, 3, 21, 22, 30];
var doubledEvens = [i * 2 for (i of numbers) if (i % 2 === 0)];
console.log(doubledEvens); // logs 4,44,60

配列内包の角括弧は、目的のスコーピングのための暗黙的なブロックをご紹介します。(例ではiのような)新しい変数はまるでletを使用して宣言されたかのように扱われます。これは内包表記の外側で利用可能はないことを意味します。

配列内包表記への入力は配列である必要はありません。また、iterators and generatorsが使用されます。

文字列でさえ入力として使用されます。上記の(配列オブジェクトのもとでの)filterと mapのアクションを実現するため:

var str = 'abcdef';
var consonantsOnlyStr = [c for (c of str) if (!(/[aeiouAEIOU]/).test(c))  ].join(''); // 'bcdf'
var interpolatedZeros = [c+'0' for (c of str) ].join(''); // 'a0b0c0d0e0f0'

ここでも、入力フォームが保存されていません。だから、文字列に戻すためにjoin()を使用する必要があります。

Typed Arrays

JavaScript typed arraysは配列オブジェクトです。そして、生のバイナリデータをアクセスするためのメカニズムを提供します。既に知っているように、 Arrayオブジェクトは成長し、動的に縮小し、任意のJavaScriptの値を持つことができます。JavaScriptエンジンは最適化を行います。そのため、これらの配列は高速です。しかしながら、オーディオやビデオ操作のような機能を追加して、Webアプリケーションはさらにパワフルになり、WebSocketsなどを使用して生のデータにアクセスするので、JavaScriptのコードがtyped arrays内の生のバイナリデータをすばやく簡単に操作できるのに役に立つときがあるのは明らかになってきました。

バッファおよびビュー: typed array アーキテクチャ

最大の柔軟性と効率性を達成するためには、JavaScript typed arraysは、実装をbuffersviewsに分割しました。バッファ(ArrayBufferオブジェクトによる実装)はデータのチャンクを表すオブジェクトであります; 話すフォーマットを持っていなく、内容にアクセスするためのメカニズムを提供しません。バッファに含まれるメモリにアクセスするために、ビューを使用する必要があります。ビューはコンテキストを提供します。— すなわち、データ型、開始するオフセット、要素の数 — それは、実際のtyped arrayにデータを回します。

Typed arrays in an ArrayBuffer

ArrayBuffer

ArrayBufferはジェネリックな固定長のバイナリデータバッファを表すために使用されるデータ型です。ArrayBufferの内容を直接操作できません。かわりに、typed arrayビューか特定のフォーマットでバッファを表す{jsxref("DataView")}}を生成し、バッファの内容を読み書きするためにそれを使用します。

Typed arrayビュー

Typed arrayビューは自己説明的な名前を持っていて、Int8, Uint32, Float64などのように、すべての通常の数値型のビューを提供します。Uint8ClampedArrayという1つ特別なtyped arrayビューがあります。これは、0〜255の値をクランプします。これは、例えば、Canvas data processingに有用です。

Type Size Description Web IDL type Equivalent C type
Int8Array 1 8-bit twos complement signed integer byte int8_t
Uint8Array 1 8-bit unsigned integer octet uint8_t
Uint8ClampedArray 1 8-bit unsigned integer (clamped) octet uint8_t
Int16Array 2 16-bit twos complement signed integer short int16_t
Uint16Array 2 16-bit unsigned integer unsigned short uint16_t
Int32Array 4 32-bit twos complement signed integer long int32_t
Uint32Array 4 32-bit unsigned integer unsigned long uint32_t
Float32Array 4 32-bit IEEE floating point number unrestricted float float
Float64Array 8 64-bit IEEE floating point number unrestricted double double

詳細について、JavaScript typed arraysと異なるTypedArrayオブジェクトのレファレンスドキュメントをご覧ください。

ドキュメントのタグと貢献者

タグ: 
Contributors to this page: shide55
最終更新者: shide55,
サイドバーを隠す