Sc283(1) 情報科学応用演習I 資料 (Part 12) 

[解説] 日付 (Date) オブジェクト

(参考: 日付(Date) in とほほのJavaScriptリファレンス)

JavaScript には,日付や時刻を表わすための特別なデータ型 厳密には「データ型」ではなく「クラス」である. (日付オブジェクト) がある. 日付オブジェクトは,new 演算子で生成される.

日付オブジェクトの生成

日付オブジェクトは,new 演算子を Date(…) 関数この Date 関数は,日付オブジェクト (Date クラス) のコンストラクタ関数と呼ばれる. に作用させることによって生成できる. このときの Date(…) 関数の引数によって, 生成する日付オブジェクトの日付・時刻を指定できる:

  1. 年月日(時分秒)を別個の引数で与える.
  2. 年月日(時分秒)を一つの文字列で与える.
  3. 引数を省略する.(現在の年月日(時分秒)を意味する.)
  1. new Date(, , [, , , ])

    年,月,日,時,分,秒 を,それぞれ整数値で別個の引数として与える. ただし,月は,1月〜12月 を 0〜11 で表わし,月の数字と1つずつずれるので注意を要する. 例えば, を表わす日付オブジェクトは,

    として生成できる.また,引数の 時,分,秒 を省略することもでき, その場合は 0時0分0秒 として扱われる.

  2. new Date(文字列 )

    引数には,「年月日」または「年月日時分秒」を表わす文字列を与える. 文字列の形式は種々のものが許されるが, "// ::" または "//" という形が分かりやすい. 例えば, を表わす日付オブジェクトは,

    として生成できる.この場合の月は,通常の 1月,2月 の 1,2 なので, 上の場合のように1つずつずれることはない.

  3. new Date()

    この場合は,現在の日付・時刻を表わす日付オブジェクトを生成する.

日付オブジェクトからの情報取得

上記のように作成された日付オブジェクトは, alert(…)document.write(…) 等で出力すると, のような形式で出力される.

また,日付オブジェクトからは,その日付オブジェクトが代入されている変数 (仮に d とする) に対して, 下表のような形式で種々の情報を取り出すことができる.これらの getFullYear() などは, 日付オブジェクト (Date クラス) のメソッドと呼ばれる.

形式意味 (値)
d.getFullYear() その日付オブジェクトの年を値とする.(整数値)
d.getMonth() その日付オブジェクトの月を値とする.(0〜11 の整数値)
1月〜12月 が 0〜11 で表わされる
d.getDate() その日付オブジェクトの (月内の) 日を値とする.(1〜31 の整数値)
d.getDay() その日付オブジェクトの曜日を値とする.(0〜6 の整数値)
日曜〜土曜 が 0〜6 で表わされる
d.getHours() その日付オブジェクトの時を値とする.(0〜23 の整数値)
d.getMinutes() その日付オブジェクトの分を値とする.(0〜59 整数値)
d.getSeconds() その日付オブジェクトの秒を値とする.(0〜59 整数値)

例:「今日の曜日」

var d, day; // 日付オブジェクト,曜日

// 今日現在の日付オブジェクトを生成して d に代入する.
d = new Date();

// getDay() で曜日 (0〜6) を取得して,文字列に変換する.
// switch を使うと良い.
switch (d.getDay()) {
case 0: day = "日曜日"; break;
case 1: day = "月曜日"; break;
case 2: day = "火曜日"; break;
case 3: day = "水曜日"; break;
case 4: day = "木曜日"; break;
case 5: day = "金曜日"; break;
case 6: day = "土曜日";
}

// 上で生成した曜日 (文字列) を出力する.
document.writeln("今日は" + day + "です.");

実行可能な例例のコードと流れ図


[解説&タスク] JavaScript のオブジェクトシステム

オブジェクト

先の「連想配列」の項でふれたように, new Object() で生成された一般オブジェクトは, その内部に,名前付きで複数の値を保持することができる. この名前と値の対はプロパティと呼ばれ, オブジェクトを生成した後からでも,動的にどんどん追加することができる. 実は,一般オブジェクト以外のさまざまなオブジェクトにもプロパティを持たせることができる. 例えば,new を用いて生成される 日付オブジェクト配列オブジェクト にもプロパティを持たせることができる.

例 (Firebug のコンソールで試すとよい)

var birth = new Date("1912/6/23");
birth.who = "Alan Turing";  // プロパティの追加
alert((birth.getMonth()+1) + ""
        + birth.getDate() + "日は "
        + birth.who + " の誕生日です.");
var triplet = new Array(3);

alert(triplet.length);      // 配列の長さ(== 3)
triplet.extra = 123456;     // プロパティの追加
triplet[-1] = "minus one";  // -1 はプロパティになる
alert(triplet.extra + triplet[-1]);
alert(triplet.length);      // 配列の長さは不変(== 3)
オブジェクトのプロパティ

実際,JavaScript で扱う種々のデータのほとんどは,new を用いて生成したものでなくても,一部の例外を除き,ある種の「オブジェクト」であり, やはり同じように,プロパティを持たせることができる. 数値・文字列・真理値などの基本的なデータはオブジェクトではないので, プロパティを持たせることはできない.もっとも,これらのデータも, new Number(…)new String(…)new Boolean(…), など,new を陽にを用いて,オブジェクトとして生成することもできる. そのようにして生成したデータは,通常の数値・文字列・真理値としても扱えるし, プロパティを持たせることも可能である.

Firefox における JavaScript の本来の用途は,ブラウザや,そこに表示されている HTML文書,さらにはその文書を構成するさまざまな要素を対象に,情報を読み取ったり操作したりすることにあり, これらの「ブラウザ」・「文書」・「要素」なども,JavaScript 中ではオブジェクトとして扱われる. (→ 「JavaScript の基本文法」 (とほほのJavaScriptリファレンス))

これまでに扱ったフォームやその構成部品 (その1, その2) なども,実はある種のオブジェクトであり, そこで用いられたピリオドを使った表記は,実はプロパティの参照なのであった. (→ 「JavaScript からの参照・代入」)

例1 (Firebug のコンソールで試すとよい)

alert(document.title);
alert(document.URL);
alert(navigator.userAgent);

例2 (実行はここをクリック

<!-- 2つのイメージ jan.png とpon.png は,
     同じディレクトリ(フォルダ)内にあるものとする -->
<title>Image Change</title>
<script type="text/javascript">
<!--
function img1_Change() {
    document.images.img1.src = "pon.png";
    // 変数 document に代入されている文書オブジェクトの
    // images プロパティに代入されているオブジェクト
    // (= イメージをまとめたオブジェクト) の
    // img1 プロパティに代入されているイメージオブジェクトの
    // src プロパティに "pon.png" を代入している.
    // document.images["img1"].src = "pon.png"; でもよい
    // document.img1.src = "pon.png"; でもよい
}
//-->
</script>

<body>
<img name="img1" src="jan.png" alt="jan-pon" onclick="img1_Change();">
<img name="img2" src="jan.png" alt="jan-pon" onclick="this.src='pon.png';">
<!-- 上の this は,この img2 という名のイメージオブジェクトを表わす -->
<!-- 下の this は,この img3 という名のイメージオブジェクトを表わす -->
<img name="img3" src="jan.png" alt="jan-pon"
     onmouseover="this.src='pon.png';"
     onmouseout="this.src='jan.png';">
</body>

メソッド

JavaScript では関数もオブジェクトであり,関数の定義

function 関数名(仮引数) {
    関数定義の本体
}

は,仮引数関数定義の本体 で表わされる関数オブジェクトを生成して,関数名 という変数に代入するのに等しい.したがって,この関数オブジェクトは, 他の変数に代入して使うこともできる.

例 (実行はここをクリック

var sq = Math.sqrt; // Mathパッケージの平方根関数を変数sqに代入
alert(sq(2));       // sq (に代入されている関数オブジェクト) の呼び出し

function foo (x) { return "" + x + ""; }
foo.word = "ヲホホホ";  // 関数オブジェクトにもプロパティを持たせられる
alert(foo(foo.word));

var bar = foo;
foo.word = "をほほほ";
alert(bar(bar.word)); // foo と bar は同じ
オブジェクト

この関数オブジェクトは,他のオブジェクトのプロパティに代入することもできるので, あるオブジェクトを操作するための関数を,そのオブジェクトのプロパティに代入しておくことで, 操作対象であるデータ (オブジェクトとそのプロパティ) と,それを操作するもの (関数) を一体化 (カプセル化) することができる. そのような,プロパティに代入された関数をメソッドと呼ぶ. JavaScript 以外のオブジェクト指向言語では,関数をオブジェクトとして扱わないのが一般的であり, メソッドは特定のクラスにのみ適用可能な関数として定義することが多い.

メソッドの実行中は,そのメソッドを保持しているオブジェクトを,this という特別な変数で参照することができる.したがって,メソッド中で this に対して種々の操作を行うことで,「その」オブジェクトを操作することができる.

例 (実行はここをクリック

// 長方形(this) の面積を計算する関数
function rectangleArea() {
  // 長方形(this) の width プロパティと height プロパティの積を返す
  return this.width * this.height;
}

// 長方形の定義
var rect1 = new Object();
rect1.width = 50;           // 幅
rect1.height = 30;          // 高さ
rect1.area = rectangleArea; // 面積計算メソッド

// メソッドの実行
alert(rect1.area());
メソッド

クラス

先の例のような「長方形」オブジェクトをたくさん作りたい場合, プロパティの初期値を与える手続きをあらかじめ定義しておき,必要に応じて呼び出せるようにできれば便利である. JavaScript では,このような手続きをある種の関数として定義でき,その関数と new 演算子を組み合わせることで, 新たなオブジェクトの生成と (プロパティの) 初期化ができる. このような関数はコンストラクタ関数と呼ばれる.

コンストラクタ関数の中では,メソッドの場合と同じように, 生成されたオブジェクトが this という変数で参照できるので, それを用いたオブジェクトの (プロパティの) 初期化が可能になっている.

例 (実行はここをクリック

// 長方形(this)の面積を計算する関数
function rectangleArea() {
  return this.width * this.height;
}

// 長方形クラス(Rectangleクラス)のコンストラクタ関数
function Rectangle(w,h) {
    this.width = w;            // 幅
    this.height = h;           // 高さ
    this.area = rectangleArea; // 面積計算メソッド
}

// 「長方形」オブジェクトの生成 (new + コンストラクタ関数)
var rect1 = new Rectangle(50,30);   // 長方形1
var rect2 = new Rectangle(25,15);   // 長方形2

// メソッドの実行
alert(rect1.area());    // 長方形1 の面積
alert(rect2.area());    // 長方形2 の面積

上の例で var rect1 = new Rectangle(50,30); が実行されたとき, 以下のような手順で「長方形」オブジェクトが作られ初期化される.

  1. 新しいオブジェクトが作られる.
  2. その新しいオブジェクトを this に代入した形で Rectangle(50,30) が実行される.
    1. this に代入されている (新しい) オブジェクトの width プロパティに引数の 50 が代入される.
    2. 同じオブジェクトの height プロパティに引数の 30 が代入される.
    3. 同じオブジェクトの area プロパティに,関数オブジェクト rectangleArea が代入される.
  3. Rectangle(50,30) が実行された後のオブジェクトを rect1 に代入する.

同じコンストラクタ関数から生成されるオブジェクトは,通常,すべて同じ名前のプロパティを持ち, 同じメソッドを持つ.このようなオブジェクトの集まりをクラスと呼び, そのクラスに属するオブジェクトの一つ一つをインスタンスと呼ぶ JavaScript 以外のオブジェクト指向言語では,コンストラクタ関数は用いずに, プロパティ・メソッド等の定義をまとめたものをクラスの定義とするものが多い. その場合,インスタンスの生成はシステムに組み込みの機構を使い, プロパティ等の初期化は初期化用のメソッドを用意する場合などが多い.. クラスは,オブジェクトの種類をあらわすものと考えることもできる. 日付 (Date)配列 (Array), ドキュメント (Document), フォーム (Form), フォームの部品 (Element) 等々もクラスである.

名前空間としてのオブジェクト

オブジェクトのプロパティの名前は,そのオブジェクト内でのみ用いられ,(そのオブジェクト外の) 他の名前と重複しても混同することはない. そのため,他と混同しては困る一群の変数や関数をひとまとめにするためにオブジェクトを用いることもある. Math パッケージ は,主にそのような用途に用いられるオブジェクトである.

オブジェクト指向プログラミング

プログラムを設計する際に,プログラムに必要なデータやユーザーインターフェースをクラスとして抽象化し, その (インスタンスとしての) 個々のデータに対する必要な操作をメソッドとして記述していくような設計手法を オブジェクト指向プログラミング と呼ぶ.

例 (実行はここをクリック

// Point クラスの定義 (点(座標値)を表す)
function Point(px, py) {            // px, py は座標値
  this.x = px;
  this.y = py;
  this.toString = toStringPoint;
  this.move = movePoint;
}
function toStringPoint () {         // 文字列表記を得るメソッド
  return "(" + this.x + ", " + this.y +")";
}
function movePoint(dx, dy) {        // 移動させるメソッド (dx, dy は移動量)
  this.x = this.x + dx;
  this.y = this.y + dy;
}

// Triangle クラスの定義
function Triangle(P, Q, R) {        // P, Q, R は頂点 (Pointクラス)
  this.v = [P, Q, R];   // 頂点の配列
  this.toString = toStringTriangle;
  this.median = medianTriangle;
  this.move = moveTriangle;
}
function toStringTriangle(dx, dy) { // 文字列表記を得るメソッド
  return this.v[0].toString() + "-" + this.v[1].toString() + "-" + this.v[2].toString();
}
function medianTriangle() {         // 重心を返すメソッド (戻り値はPointクラス)
  return new Point(
    (this.v[0].x + this.v[1].x + this.v[2].x)/3,
    (this.v[0].y + this.v[1].y + this.v[2].y)/3
  );
}
function moveTriangle(dx, dy) {     // 移動させるメソッド (dx, dy は移動量)
  this.v[0].move(dx, dy);
  this.v[1].move(dx, dy);
  this.v[2].move(dx, dy);
}


// テスト
var
A = new Point(10,0),
B = new Point(10,10),
C = new Point(0,10),
ABC = new Triangle(A, B, C);

alert("点A : " + A.toString());
alert("点B : " + B.toString());
alert("点C : " + C.toString());
alert("三角形ABC : " + ABC.toString());
alert("三角形ABCの重心 : " + ABC.median().toString());

B.move(10, 10);
alert("\n点Bを(+10, +10)移動");
alert("点B : " + B.toString());
alert("三角形ABC : " + ABC.toString());
alert("三角形ABCの重心 : " + ABC.median().toString());

ABC.move(-10, -10);
alert("\n三角形ABCを(-10, -10)移動");
alert("三角形ABC : " + ABC.toString());
alert("三角形ABCの重心 : " + ABC.median().toString());