5.1 配列とオブジェクト、for...in、forEachループ

(1/1)
ブロックのおもちゃのイラスト
Excel表にした社員名簿は2次元配列を使ってデータ化することができる。だが、職掌などによって社員1人1人の属性(プロパティ)が異なる場合、オブジェクトにした方がデータ活用がしやすくなる。
今回は、配列とオブジェクトを比較することで、JavaScriptのオブジェクトの仕組みを学んでいく。今回はプロパティまでで、メソッドについては次回以降に譲る。

目次

サンプル・プログラム

圧縮ファイルの内容
employeeList1.html社員名簿(配列形式)
employeeList2.html社員名簿(オブジェクト形式)
employeeList3.html社員名簿(構造変更可能)
arrayCase1.html条件分岐を配列にする

社員名簿(配列形式)

下表の社員名簿を一覧表示するプログラムが "employeeList1.html" である。
今期売上は営業職のみに登録されている点、社員番号091001の成田祥三さんは所属部署を兼務している点に注意してほしい。
社員名簿(配列)
まず、この社員名簿を2次元配列 EMPLOYEE_LIST に代入する。

  24: //社員名簿(配列形式)
  25: const EMPLOYEE_LIST = [
  26: ['094011', '相馬', '豊司',   '男', '1994/4/1',  '営業部', '営業', 52600],
  27: ['099004', '原口', '奈緒子', '女', '1999/7/5',  '人事部', '事務', -1],
  28: ['012023', '足立', '俊康',   '男', '2012/3/12', 'システム営業部', '技術', -1],
  29: ['004002', '畠山', '忠秋',   '男', '2004/4/1',  '経理部', '事務', -1],
  30: ['013010', '島崎', '晴生',   '男', '2013/4/1',  '営業部', '営業', 23800],
  31: ['096008', '丹羽', '麻樹',   '女', '1996/4/1',  '営業部', '営業', 31600],
  32: ['096011', '谷本', '房実',   '女', '1996/4/1',  '経理部', '事務', -1],
  33: ['020017', '深沢', 'つばさ', '男', '2020/4/1', 'システム営業部', '営業', 42800],
  34: ['007005', '川島', '武久',   '男', '2007/4/1',  '営業部', '営業', 32700],
  35: ['091001', '成田', '祥三',   '男', '1991/4/1',  '開発部,システム営業部', '技術', -1]
  36: ];

営業職以外は今期売上(要素番号7)にあり得ない数字として -1 を代入している。
所属の兼務は、カンマ区切りにして1つのテキストにした。

  50: /**
  51:  * 社員名簿を一覧表示する.
  52:  * @param   Array persons 社員名簿(2次元配列)
  53:  * @return  なし
  54: */
  55: function dispTable1(persons) {
  56:     //エラーメッセージをクリア
  57:     document.getElementById('error').innerHTML = '';
  58: 
  59:     //配列のバリデーション
  60:     if (! Array.isArray(persons)) {
  61:         //エラーを表示
  62:         document.getElementById('error').innerHTML = 'エラー:正しい社員名簿を用意してください.';
  63: 
  64:     } else {
  65:         //売上合計と営業職を集計
  66:         let n = 0;      //営業職の人数
  67:         let sum = 0;    //合計売上
  68:         for (let i = 0i < persons.lengthi++) {
  69:             let a = parseFloat(persons[i][7]);
  70:             //数字以外が含まれていたらNaNを代入して脱出
  71:             if (Number.isNaN(a)) {
  72:                 n = sum = NaN;
  73:                 return;
  74:             //合計値,人数に加算
  75:             } else if (a >0) {
  76:                 n++;
  77:                 sum +a;
  78:             }
  79:         }
  80: 
  81:         //社員名簿の1行目
  82:         html =`
  83: <tr>
  84: <th>社員番号</th><th>姓</th><th>名</th><th>性別</th><th>入社日</th>
  85: <th>所属部署</th><th>職掌</th><th>今期売上<br>(千円)</th>
  86: </tr>
  87: `;
  88:         for (let i = 0i < persons.lengthi++) {
  89:             html +"<tr>\n";
  90:             //社員番号~職掌
  91:             for (let j = 0j < 7j++) {
  92:                 html +'<td>' + persons[i][j+ '</td>\n';
  93:             }
  94:             //売上
  95:             if (EMPLOYEE_LIST[i][7>0) {
  96:                 let m = persons[i][7].toLocaleString();
  97:                 html +'<td class="num">' + m + '</td>\n';
  98:             } else {
  99:                 html +'<td>&nbsp;</td>\n';
 100:             }
 101:         }
 102:             html +=`
 103: <tr>
 104: <td colspan="7">売上合計</td>
 105: <td class="num">${sum.toLocaleString()}</td>
 106: </tr>
 107: <tr>
 108: <td colspan="7">売上平均</td>
 109: <td class="num">${(sum / n).toLocaleString()}</td>
 110: </tr>
 111: `;
 112:         //結果を表示
 113:         document.getElementById('tableEmployeeList').innerHTML = html;
 114:     }
 115: }

名簿はTABLEタグにして一覧表示するが、この処理を行うユーザー定義関数 dispTable1 は、「4.4 配列と引数の渡し方」で作ったプログラムとほぼ同じである。

名簿の表示はできたものの、データを2次利用しようとすると問題が出てくる。
まず、今期売上がない職種に -1 を代入しているが、売上に対して何か統計処理を仕様とすると、いちいち -1 かどうかをチェックしなければならない。NaN を代入しておくという方法もあるが、そもそも属性として売上をもっていない職種にデータ項目を与えるべきだろうか。
もう1つは兼務者である。絞り込み機能をつけて "システム営業部" で絞り込もうとすると、兼務者の絞り込みに一工夫必要である。
さらに、1つのデータ項目に2つ以上のデータが入るのは所属だけではないだろう。夫婦別姓制度の関心が高まっている時代である。旧姓登録のために、姓を複数登録できるようにした方がいいかもしれない。

社員名簿(オブジェクト形式)

こういうとき オブジェクトを使うと、柔軟性のある社員名簿を作ることができる。
社員名簿を下表のように考え直す。
社員名簿(オブジェクト)
2次元配列の2次元目の列に相当するデータ項目を、number, last_name, first_name‥‥という名前をもったプロパティに置き換える。今期売上 sales を持たない社員には、売上データを代入しない。また、兼務者については、所属 department を配列として代入する。
これをプログラムにしたものが "employeeList2.html" である。
まず、この社員名簿をオブジェクト配列 EMPLOYEE_LIST に代入する。

  24: //社員名簿(オブジェクト形式)
  25: const EMPLOYEE_LIST = [
  26: {
  27: number:     '094011',
  28: last_name:  '相馬',
  29: first_name: '豊司',
  30: sex:        '男',
  31: hire:       '1994/4/1',
  32: department: '営業部',
  33: duties:     '営業',
  34: sales:      52600
  35: }, {
  36: number:     '099004',
  37: last_name:  '原口',
  38: first_name: '奈緒子',
  39: sex:        '女',
  40: hire:       '1999/7/5',
  41: department: '人事部',
  42: duties:     '事務'
  43: }, {
  44: number:     '012023',
  45: last_name:  '足立',
  46: first_name: '俊康',
  47: sex:        '男',
  48: hire:       '2012/3/12',
  49: department: 'システム営業部',
  50: duties:     '技術'
  51: }, {
  52: number:     '004002',
  53: last_name:  '畠山',
  54: first_name: '忠秋',
  55: sex:        '男',
  56: hire:       '2004/4/1',
  57: department: '経理部',
  58: duties:     '事務'
  59: }, {
  60: number:     '013010',
  61: last_name:  '島崎',
  62: first_name: '晴生',
  63: sex:        '男',
  64: hire:       '2013/4/1',
  65: department: '営業部',
  66: duties:     '営業',
  67: sales:      23800
  68: }, {
  69: number:     '096008',
  70: last_name:  '丹羽',
  71: first_name: '麻樹',
  72: sex:        '女',
  73: hire:       '1996/4/1',
  74: department: '営業部',
  75: duties:     '営業',
  76: sales:      31600
  77: }, {
  78: number:     '096011',
  79: last_name:  '谷本',
  80: first_name: '房実',
  81: sex:        '女',
  82: hire:       '1996/4/1',
  83: department: '経理部',
  84: duties:     '事務',
  85: }, {
  86: number:     '020017',
  87: last_name:  '深沢',
  88: first_name: 'つばさ',
  89: sex:        '男',
  90: hire:       '2020/4/1',
  91: department: 'システム営業部',
  92: duties:     '営業',
  93: sales:      42800
  94: }, {
  95: number:     '007005',
  96: last_name:  '川島',
  97: first_name: '武久',
  98: sex:        '男',
  99: hire:       '2007/4/1',
 100: department: '営業部',
 101: duties:     '営業',
 102: sales:      32700
 103: }, {
 104: number:     '091001',
 105: last_name:  '成田',
 106: first_name: '祥三',
 107: sex:        '男',
 108: hire:       '1991/4/1',
 109: department: ['開発部', 'システム営業部'], 
 110: duties:     '技術'
 111: }];

オブジェクトは、次のようにして代入する。
let/const 変数名 = {
    プロパティ1: 値1,
    プロパティ2: 値2,
    ‥‥
    プロパティn: 値
}
ここでは、社員1人1人が1つのオブジェクトになっており、それを配列 EMPLOYEE_LIST に代入している。
const EMPLOYEE_LIST = [
    { 社員1のオブジェクト},
    { 社員2のオブジェクト},
    ‥‥
    { 社員nのオブジェクト},
];
今期売上を持たない社員には、プロパティsales を代入しない。
兼務者については、プロパティ department に配列を代入している。

このような配列やオブジェクトを、とくに JSON(JavaScript Object Notation)形式と呼ぶ。詳しくは「6.5 ファイル・アクセス、同期・非同期、JSON」で説明する。

 156: /**
 157:  * 社員名簿を作成
 158:  * @param   Array EMPLOYEE_LIST 社員名簿(オブジェクト)
 159:  * @return  String TABLEタグ
 160: */
 161: function dispTable2(persons) {
 162:     //エラーメッセージをクリア
 163:     document.getElementById('error').innerHTML = '';
 164: 
 165:     //配列のバリデーション
 166:     if (! Array.isArray(persons)) {
 167:         //エラーを表示
 168:         document.getElementById('error').innerHTML = 'エラー:正しい社員名簿を用意してください.';
 169: 
 170:     //社員名簿を作成
 171:     } else {
 172:         //社員名簿の1行目
 173:         html =`
 174: <tr>
 175: <th>社員番号</th><th>姓</th><th>名</th><th>性別</th><th>入社日</th>
 176: <th>所属部署</th><th>職掌</th><th>今期売上<br>(千円)</th>
 177: </tr>
 178: `;
 179:         let sum = 0;
 180:         let n = 0;
 181:         for (let i = 0i < persons.lengthi++) {
 182:             html +'<tr>';
 183:             html +makeColumn(persons[i], 'number');
 184:             html +makeColumn(persons[i], 'last_name');
 185:             html +makeColumn(persons[i], 'first_name');
 186:             html +makeColumn(persons[i], 'sex');
 187:             html +makeColumn(persons[i], 'hire');
 188:             html +makeColumn(persons[i], 'department');
 189:             html +makeColumn(persons[i], 'duties');
 190:             html +makeColumn(persons[i], 'sales');
 191:             html +'</tr>';
 192: 
 193:             //売上
 194:             if (typeof persons[i].sales !== 'undefined') {
 195:                 sum +parseFloat(persons[i].sales);
 196:                 n++;
 197:             }
 198:         }
 199:             html +=`
 200: <tr>
 201: <td colspan="7">売上合計</td>
 202: <td class="num">${sum.toLocaleString()}</td>
 203: </tr>
 204: <tr>
 205: <td colspan="7">売上平均</td>
 206: <td class="num">${(sum / n).toLocaleString()}</td>
 207: </tr>
 208: `;
 209:         //結果を表示
 210:         document.getElementById('tableEmployeeList').innerHTML = html;
 211:     }
 212: }

オブジェクト配列を一覧表示する処理はユーザー定義関数 dispTable2 で行う。
売上プロパティ sales がないかどうか typeof 演算子で判定し、あれば合計と人数を加算している。

 125: /**
 126:  * 社員名簿を作成:1つのカラム
 127:  * @param   Object obj 社員1名分のオブジェクト
 128:  * @param   String key プロパティ名
 129:  * @return  String 1つ分のtdタグ
 130: */
 131: function makeColumn(obj, key) {
 132:     let html = '';
 133: 
 134:     //未定義
 135:     if (typeof obj[key] == 'undefined') {
 136:         html = '<td>&nbsp;</td>';
 137:     //売上
 138:     } else if (key == 'sales') {
 139:         html +'<td class="num">' + obj[key].toLocaleString() + '</td>';
 140:     //配列
 141:     } else if (Array.isArray(obj[key])) {
 142:         html +'<td>';
 143:         for (let i = 0i < obj[key].lengthi++) {
 144:             if (i > 0)  html +'<br />';
 145:             html +obj[key][i].toString();
 146:         }
 147:         html +'</td>';
 148:     //その他
 149:     } else {
 150:         html +'<td>' + obj[key].toString() + '</td>';
 151:     }
 152: 
 153:     return html;
 154: }

1人分の名簿をTDタグにする処理はユーザー定義関数 makeColumn に分離した。引数として渡したプロパティによって、出力形式を変えている。
この関数を拡充すれば、複雑なデータ構造の名簿でも扱うことができるようになる。

forEachループ

"employeeList2.html" を読みやすいプログラムにするとともに、社員名簿の構造に自由度を持たせるためにリファクタリングする。

  24: //社員名簿(オブジェクト配列)【変更可能】
  25: //冒頭行は必須.属性と値は自由に追加・変更・削除できる.salesは売上合計対象.
  26: const EMPLOYEE_LIST = [
  27: //--冒頭行は見出し
  28: {
  29: number:     '社員番号',
  30: last_name:  '姓',
  31: first_name: '名',
  32: sex:        '性別',
  33: hire:       '入社日',
  34: department: '所属部署',
  35: duties:     '職掌',
  36: sales:      '今期売上<br>(千円)'
  37: //--以下が名簿本体
  38: }, {
  39: number:     '094011',
  40: last_name:  '相馬',
  41: first_name: '豊司',
  42: sex:        '男',
  43: hire:       '1994/4/1',
  44: department: '営業部',
  45: duties:     '営業',
  46: sales:      52600
  47: }, {
  48: number:     '099004',
  49: last_name:  '原口',
  50: first_name: '奈緒子',
  51: sex:        '女',
  52: hire:       '1999/7/5',
  53: department: '人事部',
  54: duties:     '事務'
  55: }, {
  56: number:     '012023',
  57: last_name:  '足立',
  58: first_name: '俊康',
  59: sex:        '男',
  60: hire:       '2012/3/12',
  61: department: 'システム営業部',
  62: duties:     '技術'
  63: }, {
  64: number:     '004002',
  65: last_name:  '畠山',
  66: first_name: '忠秋',
  67: sex:        '男',
  68: hire:       '2004/4/1',
  69: department: '経理部',
  70: duties:     '事務'
  71: }, {
  72: number:     '013010',
  73: last_name:  '島崎',
  74: first_name: '晴生',
  75: sex:        '男',
  76: hire:       '2013/4/1',
  77: department: '営業部',
  78: duties:     '営業',
  79: sales:      23800
  80: }, {
  81: number:     '096008',
  82: last_name:  '丹羽',
  83: first_name: '麻樹',
  84: sex:        '女',
  85: hire:       '1996/4/1',
  86: department: '営業部',
  87: duties:     '営業',
  88: sales:      31600
  89: }, {
  90: number:     '096011',
  91: last_name:  '谷本',
  92: first_name: '房実',
  93: sex:        '女',
  94: hire:       '1996/4/1',
  95: department: '経理部',
  96: duties:     '事務',
  97: }, {
  98: number:     '020017',
  99: last_name:  '深沢',
 100: first_name: 'つばさ',
 101: sex:        '男',
 102: hire:       '2020/4/1',
 103: department: 'システム営業部',
 104: duties:     '営業',
 105: sales:      42800
 106: }, {
 107: number:     '007005',
 108: last_name:  '川島',
 109: first_name: '武久',
 110: sex:        '男',
 111: hire:       '2007/4/1',
 112: department: '営業部',
 113: duties:     '営業',
 114: sales:      32700
 115: }, {
 116: number:     '091001',
 117: last_name:  '成田',
 118: first_name: '祥三',
 119: sex:        '男',
 120: hire:       '1991/4/1',
 121: department: ['開発部', 'システム営業部'], 
 122: duties:     '技術'
 123: }];

まず、社員名簿のオブジェクト配列 EMPLOYEE_LIST の冒頭(最初の要素)に、属性と表示するときの見出し(ラベル名)の対応を追加した。社員名簿の構造を自在に変更できるようにするための布石である。

 137: /**
 138:  * 社員名簿から属性一覧を取得する.
 139:  * @param   Object header 社員名簿の冒頭行
 140:  * @return  Array 属性一覧
 141: */
 142: function getProperties(header) {
 143:     let properties = Object();
 144:     for (const property in header) {
 145:         properties[property] = header[property];
 146:     }
 147:     return properties;
 148: }

社員名簿のオブジェクト配列 Persons の最初の要素から、属性と表示するときの見出し(ラベル名)をオブジェクト変数に格納するユーザー関数 getProperties を新たに追加した。
forループの中が "property in header" という書き方になっているが、これは、オブジェクト header にある属性1つ1つに対してループ処理を行うことを意味する。属性値は property に格納する。
この for...inループを使うことで、ループカウンタを意識しなくても、オブジェクトの全要素に対して漏れなくループ処理を行うことができる。

 181: /**
 182:  * 社員名簿をTABLEタグの形で返す.
 183:  * @param   Array persons 社員名簿(オブジェクト配列)
 184:  * @return  String TABLEタグ
 185: */
 186: function getTable3(persons) {
 187:     let sum = 0;
 188:     let n = 0;
 189:     let properties = Object();
 190:     let html = '';
 191:     persons.forEach(function(person, i) {
 192:         //冒頭行
 193:         if (i === 0) {
 194:             //社員名簿の属性一覧を取得する.
 195:             properties = getProperties(person);
 196:             //見出しを作成する.
 197:             html +'<tr>\n';
 198:             for (const property in properties) {
 199:                 html +'<th>' + properties[property+ '</th>\n';
 200:             }
 201:             html +'</tr>\n';
 202:         //名簿を作成する.
 203:         } else {
 204:             html +'<tr>\n';
 205:             for (const property in properties) {
 206:                 html +makeColumn(person, property);
 207:             }
 208:             html +'</tr>\n';
 209:             //売上合計に加算する.
 210:             if (typeof person.sales !== 'undefined') {
 211:                 sum +parseFloat(person.sales);
 212:                 n++;
 213:             }
 214:         }
 215:     });
 216: 
 217:     //売上合計を表示する.
 218:     html +=`
 219: <tr>
 220: <td colspan="7">売上合計</td>
 221: <td class="num">${sum.toLocaleString()}</td>
 222: </tr>
 223: <tr>
 224: <td colspan="7">売上平均</td>
 225: <td class="num">${(sum / n).toLocaleString()}</td>
 226: </tr>
 227: `;
 228:     return html;
 229: }

配列の全ての要素に対して漏れなくループ処理を行うのに、forEachメソッドがある。
forEachメソッドの引数にはコールバック関数を記述する。コールバック関数の第1引数には要素の値が、第2引数には要素のインデックスが、第3引数には操作されている配列が入る。これらの引数は省略可能であるが、ここでは第1引数と第2引数を利用する。
if〜else文を使い、冒頭行の時は見出しを、それ以外は名簿の行としてHTMLタグを生成していく。前述の getProperties関数で取得した属性を列として一覧表を作成する。
こうして、社員数(行数)や属性数(列数)を制約するようなカウンタ変数を排除することで、名簿の構造(オブジェクトの構造)は自在に変更できるようになり、関数 getTable3 の見通しも良くなった。

for...inforEachループを利用することで、行・列の数を意識する必要がなくなった。つまり、列を自在に増やしたり減らしたりできるし、行数(人数)の制約もなくなった。
オブジェクト配列 EMPLOYEE_LIST の冒頭に用意した属性一覧に含まれていれば、その順序で社員名簿を一覧表示することができる。試しに変更してみてほしい。

読みやすいプログラム:ループ処理

ループ処理では、無限ループに陥ったり、開始と終了の抜け漏れを避けなければならない。そこで、ループ条件は単純化し、ループ制御に使う変数を複数箇所で変更することがないようにするのが読みやすいプログラムである。

ループ条件を1箇所に集めることができるという観点では、whileループよりforループを使うといい
ただし、forループは開始/終了条件のバグがあっても走らせてみないとわからないので、配列全体に一斉に同じ作用をさせるなら、今回紹介した forEachメソッドを使おう。元の配列を残して新しい配列を生成したいような場合は、「5.3 インスタンス」で紹介する mapメソッドを使って簡明に書くことができる。
オブジェクトに対してループ処理を行う場合は、今回紹介した for...inループを使おう。全要素に対して漏れなくループ処理を適用できる。

なお、JavaScriptのループ処理は同期していることが前提である。ループ処理中の配列に対して非同期処理で変化が加わるようなことは避けること

読みやすいプログラム:条件分岐を配列にする

3.2 switch~case文」では、次のようなプログラムを紹介した。

  21: /**
  22:  * 判定と画面表示
  23: */
  24: function switchCase1() {
  25:     //変数宣言
  26:     let month = document.getElementById('month').value;     //月
  27:     month = parseInt(month, 10);                            //10進整数化
  28:     let ret;
  29: 
  30:     //月の大小判定
  31:     switch (month) {
  32:         case 1:
  33:         case 3:
  34:         case 5:
  35:         case 7:
  36:         case 8:
  37:         case 10:
  38:         case 12:
  39:             ret = '大の月';
  40:             break;
  41:         case 2:
  42:         case 4:
  43:         case 6:
  44:         case 9:
  45:         case 11:
  46:             ret = '小の月';
  47:             break;
  48:         default:
  49:             ret = 'エラー:1以上12以下の整数を入力してください';
  50:             break;
  51:         
  52:     }
  53: 
  54:     //結果を表示する
  55:     document.getElementById('ret').innerHTML = ret;
  56: }

if~else文より見やすくなったとはいえ、月の数字1~12の順序が入れ子になって見通しが悪い。このように列挙型の条件分岐の場合、条件分岐を止めて、配列 months に対象(ここでは月の大小)を代入し、findメソッドを適用することを考えてみる。

  21: /**
  22:  * 判定と画面表示
  23: */
  24: function arrayCase1() {
  25:     //月の大小判定の配列;0月はundefined
  26:     const months = [undefined, '大の月', '小の月', '大の月', '小の月', '大の月', '小の月', '大の月', '大の月', '小の月', '大の月', '小の月', '大の月'];
  27: 
  28:     //変数宣言
  29:     let month = document.getElementById('month').value;     //月
  30:     month = parseInt(month, 10);                            //10進整数化
  31: 
  32:     //月の大小判定
  33:     let ret = months.find(function (element, index) { return index === month });
  34:     if (ret == undefined)   ret = 'エラー:1以上12以下の整数を入力してください';
  35: 
  36:     //結果を表示する
  37:     document.getElementById('ret').innerHTML = ret;
  38: }

findメソッドは引数にコールバック関数を指定する。コールバック関数の第1引数は要素、第2引数は添字である。コールバック関数の return のところに条件式を記入してやることで、この条件に一致する最初の要素を返す。
ここでは、添字は月の数字であるから、前述の switch~case文で実行したのと同じ結果が得られる。

なお、このプログラムのように配列 months に代入すると、添字は0からスタートで、1, 2, 3‥‥と増えてゆく。0月はあり得ないので、要素に undefined を代入するようにした。また、-1以下の添字や、13以上の添字を findメソッドで探そうとすると undefined が返ることから、undefined が返ってきたらエラーメッセージを表示するようにした。

このように、列挙型の条件分岐は配列とfindメソッドを使うことで読みやすいプログラムになる。

コラム:オブジェクトとは

ミクロコスモスとマクロコスモス
プロパティは属性とも呼ばれる。たとえば人間を1つのオブジェクトとみなすと、数多くの属性が詰め込まれていることが分かるだろう。

ジェンダー平等というものの、男性と女性とでは備える属性が微妙に異なる。また、年齢や学歴によって付加される属性が変わってくる。
結婚すると、さらに属性が加わり、配偶者という別のオブジェクトとの関係性が生まれる。子どもが産まれると、あらたなオブジェクトが生成され、関係性が追加される‥‥。

何かのデータの集合体を扱おうとする時、データ項目を整理してExcel表に収めようとするのではなく、そのデータ集合体の属性を忠実に表そうとするのがオブジェクト指向である。

今回、JSON形式について簡単に触れたが、じつは JSON形式はリレーショナルデータベースのテーブル構造に対応させることができる。配列が行で、プロパティが列に対応すると考えてほしい。
JavaScriptは直接データベースを扱うことはできないが、「第7章 WebAPIとjQuery」で紹介するが、データベースからJSON形式でデータを出力するAPIを用意すれば、データベース処理に関わることができる。
(この項おわり)
header