-
配列の繰り返し処理では通常 for 文を使います。
for 文には一般的に指標を使って繰り返し、指標で配列を参照する方法や、 配列の指標と値を順次取得できる方法があります。
尚、for 文には以下の使い方がある様ですので、それぞれについて見ていきます。- for(指標を使った一般的な方法)
- for...in(オブジェクトのプロパティ名での繰返し)
- for...of(オブジェクトのプロパティの値の繰返し)
- Array.forEach(配列の各要素についての繰返し)
■for(指標を使った一般的な方法)
いまさらですが for 文の構文は以下の様になっています。 「初期値設定」「条件式」「指標処理」の3個の部分を「;」セミコロンで区切ります。 それぞれを [] で囲っているのは、必要が無ければ記述を省略できます。 (通常はあまり使いませんが)
for ( [ 初期値設定 ]; [ 条件式 ]; [ 指標処理 ] ) { // 繰り返しの処理 ... }基本的な使い方は以下のソースを見て下さい。
最初に3個の要素を持つ配列を宣言し、次に for で配列の長さ分の処理を行います。
配列の長さを取得するために length プロパティを参照しますが、 このプロパティは、配列の宣言を行った時に javascript が内部で設定されます。
繰返し処理の中身は配列の値をコンソールに表示することを行います。 (10 20 30 と順次表示されます。)//配列の宣言 var arr = [10, 20, 30]; //配列の内容を順次表示 for(var i = 0; i < arr.length; i++) { //繰返しの処理... console.log(arr[i]); }
「初期値設定」「条件式」「指標処理」の3個の部分はそれぞれ必要が無ければ記述しなくても問題ありません。 究極、3個とも無くしてしまってもOKです。 但し、ループを抜ける処理は記述しないと無限ループになってしまいます。
このループを抜ける処理が break 文でループを抜けたい条件の中で記述します。 (条件が無くてもOKですが...)
上の処理と同じことを行う例を示します。//配列の宣言 var arr = [10, 20, 30]; //指標の宣言 var i = 0; //for 文の中身は記述しない for( ; ; ) { if (i >= arr.length) { //length の値は「3」 //指標が長さ以上になった場合ループを抜ける break; } //ループ内処理 console.log(arr[i]); //指標を増やす i++; } //break 後はここに来る
break 文が出たところで continue 文を出さないと片手落ちなので以下の例を示します。 指標が「1」になった時に、指標を+1してループの先頭に戻しています。 結果としてコンソールには 10 30 が表示されます。//配列の宣言 var arr = [10, 20, 30]; //配列の内容を順次表示 var i = 0; //for 文の中身は記述しない for( ; ; ) { if (i >= arr.length) { //指標が長さ以上になった場合ループを抜ける break; } if (i == 1) { //指標を増やす i++; //指標が[1]ならば先頭に戻る:「if (i >= arr.length) {」の処理に戻る continue; } //ループ内処理 console.log(arr[i]); //指標を増やす i++; } //break 後はここに来る■for...in(オブジェクトのプロパティ名での繰返し)
for 文なので配列に使えるのかなと思って、以下の例を実行したのですが、 コンソールに表示されるのは「0 1 2」と指標らしきものが表示されます。 なぜ指標なのかを正式なドキュメントに当たると以下の様に記されています。
「for..in 文は、指定したオブジェクトの列挙可能プロパティに対して、順不同で反復処理をします。」
つまり返されるのはプロパティ名を返す様です。 (単純な配列の場合は指標がプロパティ扱いの様です。//配列の宣言 var arr = [10, 20, 30]; //配列の内容を順次表示 for(var v in arr) { console.log(v); }
そこで以下の様にオブジェクトに対して for 文を行うと、コンソールには「prop1 prop2 prop3」が順次表示されます。 これはオブジェクトのプロパティ名そのものです。//オブジェクトの宣言 var obj = { prop1: 10, prop2: 20, prop3: 30 }; //オブジェクトのプロパティ名を順次表示 for(var v in obj) { console.log(v); }
さらに以下の様にプロパティ名を扱うと、プロパティに対応する値にアクセスできます。
//オブジェクトの宣言 var obj = { prop1: 10, prop2: 20, prop3: 30 }; //オブジェクトの内容を順次処理 var sum = 0; var str = ""; for(var v in obj) { sum += obj[v]; // 数値として加算 str += obj[v]; // 文字列として追加 } console.log(sum); // 60 と表示される console.log(str); // 102030 と表示される
先ほどの配列の場合は以下の様にすれば、指標に対応する値にはアクセスできますが、 指標の順番通り取得できるとは限らないので、指標によるアクセスの方が良いようです。 (以下の例の様に配列の個数が少ない場合は順番にアクセスされる様ですが..)//配列の宣言 var arr = [10, 20, 30]; var sum = 0; //配列の内容を順次表示 for(var v in arr) { sum += arr[v]; // 数値として加算 } console.log(sum); // 60 と表示される■for...of(オブジェクトのプロパティの値の繰返し)
for...in ではオブジェクトのプロパティ名での繰り返し処理でしたが、 for...of はオブジェクトのプロパティの値を順次アクセスできるものです。
但し対象となるものは iterable(繰り返し可能)なオブジェクト らしいです。 配列(Arrayで宣言されたもの)や、String、Map などです。//---------- //配列の宣言 var arr = [ 10, 20, 30 ]; //配列の値を順次表示 for(var v of arr) { console.log(v); } //コンソールに以下の3行で表示される // 10 // 20 // 30 //---------- //Stringの宣言 var str = "ABC"; //Stringの文字を順次表示 for(var v of str) { console.log(v); } //コンソールに以下の3行で表示される // A // B // C //---------- //Mapの宣言 var M = new Map([["a", 1], ["b", 2], ["c", 3]]); //Mapの要素を順次表示 for (var ent of M) { console.log(ent); } //コンソールに以下の3行で表示される // Array [ "a", 1 ] // Array [ "b", 2 ] // Array [ "c", 3 ] //Mapのキーと値を順次表示 for (var [key, value] of M) { console.log(key + "=" + value); } //コンソールに以下の3行で表示される // a=1 // b=2 // c=3■Array.forEach(配列の各要素についての繰返し)
Arrayオブジェクトのメソッドである forEach を使っても繰り返し処理が行えます。 構文は以下の通りです。
arr.forEach(function callback( value [, index [, array ] ] ) { //your iterator }[, thisArg]); パラメーター: callback: 各要素に対して実行するコールバック関数で、3つの引数をとります。 value: 現在処理されている配列の要素。 index: 現在処理されている配列の要素のインデックス。 array: forEachが適用されている配列。 thisArg: callback 内で this として使用する値 (i.e the reference Object)。
forEach の例を以下に示します。
//配列の宣言 var arr = ['a', 'b', 'c']; //配列を順次処理 arr.forEach(function(val, idx) { console.log("arr[" + idx + "] = " + val); }); //コンソールに以下の3行で表示される // arr[0] = a // arr[1] = b // arr[2] = c
PR -
「連想配列の操作について(this キーワード)」の記事の中で 連想配列の様に使えるオブジェクトの説明で、そのオブジェクトの中にメソッドを作成し、 オブジェクト内の変数をアクセスする為に this キーワードを使いました。
⇒JavaScript 連想配列の操作について(this キーワード)
今回はこの this キーワードですが、使う場所によって異なるオブジェクトを指し示すため注意が必要です。
以下の使い方がある様ですので、それぞれについて見ていきます。■グローバル実行コンテクスト
以下のソースを見て下さい。 最初に this キーワードそのものをコンソールにログアウトしています。 結果として this はウインドウオブジェクトであることが分かります。 さらに次のグローバル変数宣言で、ウインドウオブジェクトに value オブジェクトを値「1」で追加します。 これで、ウインドウオブジェクトのプロパティ的に value を参照することが出来ます。
value を「2」として上書きできることも分かります。
ここで注意が必要なのは、存在しない変数をいきなり設定してやると、変数が生成されます。 以下のソースでも value2 が生成されることが分かります。■関数コンテクスト
グローバル関数の宣言を行って、その中で this キーワードで value を参照しています。 表示される結果は、グローバル変数の内容となります。
■オブジェクトのメソッドとして
オブジェクトを宣言し、その中でメソッドも宣言します。 メソッドの中で this を使ってオブジェクト内のプロパティにアクセスしています。 (このメソッドの定義はインラインでの定義と言うそうです。)
//オブジェクト宣言 var objTest = { value: 100, //オブジェクト内のメソッド宣言 logout: function() { console.log("object value = " + this.value); } }; //メソッド実行 objTest.logout(); // object value = 100 と表示される
このインラインのメソッドを、オブジェクトの外で関数として宣言し、 オブジェクトのプロパティに後から追加することもできます。//オブジェクト宣言 var objTest = { value: 200 }; //外側で関数宣言 function _logout() { console.log("object value = " + this.value); } //プロパティに関数を割り当てる objTest.logout = _logout; //メソッド実行 objTest.logout(); // object value = 200 と表示される
この例では、オブジェクトのプロパティを logout と宣言するのと、 そのプロパティを _logout 関数に置き換える処理を一緒に行っています。
一緒に行うのがいやであれば、以下の様にしても同じです。//オブジェクト宣言 var objTest = { value: 200, logout: null //取敢えず先にプロパティ宣言 // logout: 0 }; //外側で関数宣言 function _logout() { console.log("object value = " + this.value); } //プロパティに関数を割り当てる objTest.logout = _logout; //メソッド実行 objTest.logout(); // object value = 200 と表示される■コンストラクタの呼び出しとして
関数がコンストラクタとして(new キーワードとともに)使用されるとき、 その this は生成された新しいオブジェクトにバインドされます。
以下の例では最初の関数宣言では this を使って内部的にオブジェクトを生成し、そのオブジェクトのプロパティとして value を作り引数の値を設定しています。
この関数をコンストラクタ呼出しを行うと、戻り値としてオブジェクトを返すので、 それを別の変数に代入することで変数を介してそのオブジェクトへアクセスできます。 変数 obj をコンソールに表示させると、オブジェクトが生成されていることが分かります。//関数宣言 function objCreate(pVal) { this.value = pVal; // value プロパティを pVal で設定 } //コンストラクタ呼出しでオブジェクト生成 var obj = new objCreate(100); console.log(obj); // Object { value: 100 } と表示される
もし new キーワードで使用せずに単に関数呼び出しとした場合はどうなるでしょうか。 以下の例を見て下さい。 単なる関数呼び出しでの this はグローバルオブジェクトを示すため、 この場合ですと Window オブジェクトに value プロパティを生成します。//関数宣言 function objCreate(pVal) { this.value = pVal; } //単なる関数呼び出し objCreate(100); console.log(this); // Window { objCreate: function objCreate() , value: 100 ... と表示される■別オブジェクトのバインド呼び出し(call または apply 呼び出し)
関数本体に this キーワードを使用する場合、call メソッドか apply メソッドを使用した呼び出しで、 その値に特定のオブジェクトをバインドできます。
以下の例はオブジェクト「obj」を宣言し、関数の this の指定が「obj」となっていることを示します。//プロパティ「value」を持つオブジェクト宣言 var obj = { value: "object" }; //グローバルオブジェクトにプロパティ「value」宣言 var value = 'global'; //関数宣言 function objTest() { return this.value; //関数の呼出により[this]の指すものが変わる } var strRet; //通常の関数呼び出し strRet = objTest(); console.log(strRet); // global と表示される //[call]関数呼び出し strRet = objTest.call(obj); // this の指定を「obj」として呼び出し console.log(strRet); // object と表示される //[apply]関数呼び出し strRet = objTest.apply(obj);// this の指定を「obj」として呼び出し console.log(strRet); // object と表示される
call 及び apply の明確な違いは以下の例を見て下さい。 call 呼出しの場合は、 this に対応するオブジェクトの後に引数をそのままの値で設定し、 apply 呼出しの場合は、 this に対応するオブジェクトの後に引数を配列の形で設定します。//関数宣言(引数が3個) function sum(p3, p4, p5) { //[this]によるプロパティ値と引数の値の合計計算 return this.p1 + this.p2 + p3 + p4 + p5; } //プロパティ[p1][p2]を持つオブジェクト宣言 var obj = { p1: 1, p2: 2 }; var ret; //[call]による関数呼び出し ret = sum.call(obj, 3, 4, 5); console.log(ret); // 15 と表示される //[apply]による関数呼び出し ret = sum.apply(obj, [100, 200, 300]); console.log(ret); // 603 と表示される
-
連想配列とは各種のKEYに対応する値を持つ配列の様なものであると「連想配列の作成と初期化について」で説明しましたが、 JavaScriptには実際には連想配列は存在せず、オブジェクトのプロパティとして扱うことで連想配列的に扱えます。 以下の様な例があります。
連想配列的宣言
//連想配列の宣言(実際はオブジェクト) var arrVar = { item: "test1", value: 100, func: function() { // 関数の宣言 console.log("TEST"); } }; //配列内の値表示 console.log(arrVar["item"]); // test1 と表示される console.log(arrVar["value"]); // 100 と表示される //関数の実行 arrVar.func(); // TEST と表示される上の例では arrVar に関数 func を宣言していますが、このままだと何も意味のある処理ではないので arrVar が持つプロパティを表示する様にしてみます。
そこで必要になるのが this キーワードです。 this 「これ」って何といった感じですが、 this が存在するオブジェクトの親オブジェクトを指すと理解すれば良いと思います。
論より実際の処理を見ると分かりやすいです。上の例に少し修正を加えます。this を使った連想配列の項目アクセス
//連想配列の宣言(実際はオブジェクト) var arrVar = { item: "test1", value: 100, func: function() { // 関数の宣言 var str = ""; str += "item = " + this.item; str += ",value = " + this.value; console.log(str); } }; //関数の実行 arrVar.func(); // item=test1,value=100 と表示される関数 func が呼ばれた時には this が指し示すオブジェクトは、 関数オブジェクト func が属する親オブジェクトになりますので arrVar を指しそれのプロパティへのアクセスが可能になります。
いわゆるオブジェクト参照の変数ですので this を別の変数に代入しても利用できます。this を使った連想配列の項目アクセスその2
//連想配列の宣言(実際はオブジェクト) var arrVar = { item: "test1", value: 100, add: function(pVal) { // value に加算する関数宣言 this.value += pVal; }, func: function() { // 関数の宣言 var obj = this; // this を別の変数に代入 var str = ""; str += "item = " + obj.item; str += ",value = " + obj.value; console.log(str); } }; //関数の実行 arrVar.add(100); //関数の実行 arrVar.func(); // item=test1,value=200 と表示される関数 func では this を別の変数に代入して処理を行っています。 add という関数を追加してありますが、これは引数の値をプロパティ value に加算処理を行います。
今回使用した this は奥が深いキーワードでいろんな場所で使えるのですが、 詳しい説明は又の機会にしたいと思います。
-
以前の記事では配列の初期化について記しましたが、今回は配列の要素に関しての増減などを行う処理についてです。
⇒JavaScript 配列の作成と初期化について
配列を操作するメソッドには以下の様なものがあります。メソッド 構文 説明 push Array.push( value, ...) 配列の最後尾に要素を追加する。(要素は値そのもの、または配列) pop Array.pop() 配列の最後尾から要素を削除する。 unshift Array.unshift( value, ...) 配列の先頭に要素を追加する。(要素は値そのもの、または配列) shift Array.shift() 配列の先頭から要素を削除する。 concat Array = Array.concat( value, ...) 配列の最後尾に要素を追加し、結果の配列を返す。 slice Array = Array.slice( begin [, end] ) 配列の開始から終了までの要素を別の配列として返す。
終了指定が無い場合は最後の要素までが範囲とする。
(但し終了は含まれない)splice Array = Array.splice( index, howMany, [element1], ... ) 指定配列をindexで指定された位置から、howManyで指定された個数分を取除き、要素を追加する。
戻り値:削除された配列を返す。
index:値が配列の長さより大きい場合、配列の長さと同じ値となります。値が負数の場合、配列の終端からその値を引いた数が開始位置となります。
howMany:配列から取り除く古い要素の数を示す整数。howMany が 0 の場合、どの要素も取り除かれません。
配列の要素への最後尾への追加と削除、及び先頭への追加と削除の例を示します。 要素の追加は1個のみではなく連続して引数として渡せるため、そのままの順番で配列に追加されます。配列への要素の追加と削除
//配列の宣言 var arrStr = ["aaaa", "bb", "ccccc"]; console.log(arrStr); // Array(3) [ "aaaa", "bb", "ccccc" ] と表示される //要素の最後尾追加 : push arrStr.push("dddd"); console.log(arrStr); // Array(4) [ "aaaa", "bb", "ccccc", "dddd" ] と表示される //要素の最後尾削除 : pop arrStr.pop(); // "dddd" 削除 arrStr.pop(); // "ccccc"削除 console.log(arrStr); // Array(2) [ "aaaa", "bb" ] と表示される //複数要素の先頭追加 : unshift arrStr.unshift("dddd", "ee"); console.log(arrStr); // Array(4) [ "dddd", "ee", "aaaa", "bb" ] と表示される //要素の先頭削除 : shift arrStr.shift(); // "dddd"削除 console.log(arrStr); // Array(3) [ "ee", "aaaa", "bb" ] と表示される上の例では個別の要素を追加する例でしたが、追加処理の引数として配列そのものを指定できます。 以下にその例を示しますが、追加された配列は最初の配列の中の入れ子での配列になってしまいますので注意が必要です。
配列への配列の追加
//配列の宣言 var arrStr = ["aaaa", "bb", "ccccc"]; console.log(arrStr); // Array(3) [ "aaaa", "bb", "ccccc" ] と表示される //配列データの最後尾追加 : push (Array()) var arrStr2 = ["111", "222"]; arrStr.push(arrStr2); console.log(arrStr); // Array(4) [ "aaaa", "bb", "ccccc", ["111", "222"] ] と表示される
この現象を解消する為に concat を使って配列を連結し結果を新しい配列を返す様にします。 concat の戻り値は配列なので新しい配列変数に代入しても、既に在る配列変数に代入することもできます。配列の連結
//配列の宣言 var arrStr = ["aaaa", "bb", "ccccc"]; console.log(arrStr); // Array(3) [ "aaaa", "bb", "ccccc" ] と表示される //第2の配列の宣言 var arrStr2 = ["111", "222"]; //配列を連結し、新しい配列にコピー var arrStr3 = arrStr.concat(arrStr2); console.log(arrStr3); // Array(5) [ "aaaa", "bb", "ccccc", "111", "222" ] と表示される //配列を連結し、元の配列を置き換え var arrStr = arrStr.concat(arrStr2); console.log(arrStr); // Array(5) [ "aaaa", "bb", "ccccc", "111", "222" ] と表示される
配列の切出しを slice を使って行う例を以下に示します。配列の切出し
//配列の宣言 var arrStr = ["aaaa", "bb", "ccccc", "d", "eee" ]; console.log(arrStr); // Array(5) [ "aaaa", "bb", "ccccc", "d", "eee" ] と表示される //開始のみ指定 var arrStr2 = arrStr.slice(1); console.log(arrStr2); // Array(4) [ "bb", "ccccc", "d", "eee" ] と表示される //開始、終了指定 var arrStr3 = arrStr.slice(1, 4); console.log(arrStr3); // Array(3) [ "bb", "ccccc", "d" ] と表示される //開始、終了指定:終了が範囲を超えた指定 var arrStr4 = arrStr.slice(1, 10); console.log(arrStr4); // Array(4) [ "bb", "ccccc", "d", "eee" ] と表示される
配列の要素の入替を splice を使って行う例を以下に示します。配列の要素の入替
//配列の宣言 var arrStr = ["aaaa", "bb", "ccccc", "d", "eee" ]; console.log(arrStr); // Array(5) [ "aaaa", "bb", "ccccc", "d", "eee" ] と表示される //Index、削除個数、追加要素の指定 var arrStr2 = arrStr.splice(1, 2, "111", "22"); //元の配列の表示 console.log(arrStr); // Array(5) [ "aaaa", "bb", "111", "22", "d", "eee" ] と表示される //削除された配列の表示 console.log(arrStr2); // Array(2) [ "bb", "ccccc" ] と表示される
-
連想配列とは通常の配列の様に要素を指標によって参照するのではなく、キーとなる文字列とそれに対応する値を持ちます。 しかし、JavaScript では指標に文字列を指定できません。但し、 Array のプロパティとして取り扱うことで連想配列の様な振る舞いが可能です。
連想配列的宣言
//連想配列の宣言 var arrVar = { name: "test", value: "12345" }; console.log(arrVar); // Object { name: "test", value: "12345" } と表示される //個別の表示 console.log(arrVar["name"]); // test と表示される console.log(arrVar["value"]); // 12345 と表示される上の例では arrVar クラスを配列の様に宣言し生成していますが、コンソールには Object と表示されます。 これはオブジェクトのプロパティであることが分かります。
それぞれのプロパティを個別に表示させると、連想配列的に値を返します。
また、以下の例の様に、宣言された連想配列に後から要素を追加することもできます。
連想配列的宣言と値の追加
//連想配列の宣言 var arrVar = { name: "test", value: "12345" }; //連想配列への要素追加 arrVar["item"] = "aaaaaaa"; console.log(arrVar); // Object { name: "test", value: "12345", item: "aaaaaaa" } と表示される
ここで連想配列と言っているものはオブジェクトであり、その中のプロパティを宣言してそれぞれをプロパティ名(キー名)によりアクセスします。 オブジェクトのプロパティへのアクセスはドットで連結することで行えます。以下に例を示します。
連想配列のプロパティへのアクセス
//連想配列の宣言 var arrVar = { name: "test", value: "12345" }; //連想配列の各要素へのアクセス(プロパティを指定) console.log(arrVar.name); // test と表示される console.log(arrVar.value); // 12345 と表示される //要素の追加 arrVar.item = "aaaa"; console.log(arrVar.item); // aaaa と表示される console.log(arrVar); // Object { name: "test", value: "12345", item: "aaaa" } と表示されるオブジェクトへのプロパティ追加は簡単にできるところが JavaScript の自由度を高めていると思います。 (逆に言えば、プログラムを難しくしているのかもしれませんが)
実はオブジェクトには関数も持つことが出来ます。以下の例は最初に宣言したオブジェクトに対して後から関数を追加しています。
連想配列への関数追加
//連想配列の宣言 var arrVar = { name: "test", value: "12345" }; //要素の追加 arrVar.item = "aaaa"; //関数の追加 arrVar.func = function() { alert("test"); // 単にメッセージで「test」の表示 } console.log(arrVar); // Object { name: "test", value: "12345", item: "aaaa", func: func() … } と表示される //関数の実行 arrVar.func(); // 「test」の表示が行われる
この関数は後から追加しなくても、最初の宣言で行えばもっと簡素にできます。
連想配列の関数宣言
//連想配列の宣言 var arrVar = { name: "test", value: "12345", item: "aaaa", func: function() { alert("test"); // メッセージで「test」の表示 } }; console.log(arrVar); // Object { name: "test", value: "12345", item: "aaaa", func: func() … } と表示される //関数の実行 arrVar.func(); // 「test」の表示が行われる