「未分類」カテゴリーアーカイブ

CSSとJavaScript

目標

JavaScriptの醍醐味の1つは、CSSを動的に操作することができることである。
ここでは、JavaScriptからCSSを操作する方法について学ぶ。
また、HTML要素のプロパティへのアクセスについても学ぶ。

  • CSSとJavaScriptのstyleオブジェクトの関係を理解できる。
  • CSSのプロパティ名から、JavaScriptのstyleオブジェクトのプロパティ名を生成することができる。
  • JavaScriptから適切にスタイルを変更することができる。
  • JavaScriptから適切に要素のプロパティにアクセスできる。

CSS再び

CSSの文法とセレクタの指定方法

CSSでは、スタイルを羅列することによって文書の装飾をおこなっていく。
それぞれのスタイルの指定は、基本的には「どこを」「どうする」という形をしている。

セレクタ

「どこを」というのを指定するのがセレクタである。
HTML文書の中のどこ(スタイルを適用する対象の要素)を指定する場合には、色々な書き方があるが、一番簡単なのはHTMLの要素名をそのまま書くことである。
例えば「h1」と書けば、見出し1、つまりh1要素に対してスタイルが適用される。

CSSのセレクタの指定方法には様々な種類がある。
以下の表に、代表的なものをまとめる。

指定方法 説明
* { color:red; } すべての要素にスタイルを適応
div { color:red; } HTML文書内のすべてのdiv要素にスタイルを適用
div* { color:red; } 要素内の要素すべてにスタイルを適応(div要素の中に書いたもの全部)
div#hoge { color:red; } id名hogeのdiv要素にスタイルを適応
div.fuga { color:red; } class名fugaのdiv要素すべてにスタイルを適応
h1, h2 { color:red; } 指定した複数の要素にスタイルを適応
div#hoge p { color:red; } id名hogeのdiv要素の中にあるp要素にスタイルを適応(子孫セレクタ)
div:hover { color:red; } [擬似クラス]カーソルが乗っている要素にスタイルを適応
a:link { color:red; } [擬似クラス]未訪問のリンク要素にスタイルを適応
a:visited { color:red; } [擬似クラス]訪問済のリンク要素にスタイルを適応

他にも様々な指定の方法があるので、自分で調べてみるとよいだろう。

宣言(プロパティと値)

CSSでは、「どこを」指定した後には、{ }で囲んで「どうする」を記述する。
これをスタイルの宣言と呼ぶ。
宣言はプロパティと値のセットになっており、「○○: ××」という形で記述する。
ここで、○○がプロパティ、xxがそのプロパティに設定するである。
例えば、「color: blue」と書けば「文字色を青に設定する」という意味になる。
宣言が複数ある場合はセミコロンで区切って書く。
だたし、宣言が1つしか無い場合に最後に「;(セミコロン)」をつけても問題ない。
そのため、宣言の後にはセミコロンをつける習慣をつけておいた方がトラブルが少ない。

CSS文法

透明な箱

CSSで装飾を行う際に知っていると役に立つものとして、ボックスモデルといものがある。
これは要素が透明の箱でできているとみるものである。
p要素を例に考えてみよう。
以下の図では、縦横幅、枠線、外余白、内余白をCSSによって指定している。

要素を透明な箱だと思って装飾しよう

p要素で囲んだ文字列「透明な箱の構造」が透明な箱の中にあるとする。
順番は前後するが、まず、箱の大きさは縦30px×横100pxで、枠線が赤色で太さ5pxの実線で書かれているものだとする。
ここで、枠線により透明だった箱の境界線がわかる。
この枠線から内側の、文字までの間にとることができる余白が内余白(padding)で、外側にとることができる余白を外余白(margin)と言う。

つまり、要素を箱のように考えると、外余白>枠線>内余白>中身(文字や画像など)という構造になっていることがわかる。

装飾の種類

CSSをうまく使うと、Webアプリケーションのデザインをかなり作り込むことができる。
まずは、基本的な装飾例を見ていきたい。
なお、今回は文字色や背景色を変えるときの色指定を、カラーコードで行う。
また、多くの場合、指定を無効にするためにはnoneを値に設定する。

背景色を変える (ID名bar1の票素)

CSS
p#bar1{ background: #ff1493; }
表示例

ショッキングピンク

文字色を変える (ID名bar2の票素)

CSS
p#bar2{ color: #ff0000; }
表示例

文字色変わってる?

フォントを装飾する

CSS
p#bar3{ font-weight: bold; }
p#bar4{ font-weight: lighter; }
p#bar5{ font-style: italic; }
表示例

太字

細字

イタリック

テキストを装飾する

CSS
p#bar6 { text-decoration: underline; }
p#bar7 { text-decoration: overline; }
p#bar8 { text-decoration: line-through; }
p#bar9 { text-shadow: 3px 3px 2px #0000ff; }
表示例

下線

上線

打ち消し線

影:水平距離 垂直距離 半径の順 色の順で指定

テキストの位置

CSS
p#hoge10 { text-align: left; }
p#hoge11 { text-align: center; }
p#hoge12 { text-align: right; }
表示例

左寄せ

中央揃え

右寄せ

枠線をつける

CSS
p#hoge13 { border: 3px #000 solid; }
表示例

枠線:3pxの太さで黒で実線

余白を指定(比較のために枠線と色をつけています)

CSS
p#hoge14 { margin: 10px; }
p#hoge15 { padding: 10px; }
表示例

外余白:10px

枠線から文字までの間が内余白:10px

新しい装飾の種類

現在使われているCSSは主として、CSS3 (CSS Level 3)と呼ばれるものである。
CSS3では、グラデーションや透過色、2D3D変形やアニメーションなどより細かな装飾の指定が可能となっている。

CSS3で新しく追加(採用)された機能は、ブラウザに実装されなければ使うことができない。
CSSの各機能は、長い策定過程の末に仕様が標準化される。
しかし、標準化されてからブラウザに実装されるのではなく、採用される予定の機能が各ブラウザで先行実装され、策定仕様に合わせてアップデートを繰り返すことが多い。
そのため、CSSで新しい機能が採用されてると、既に一般的なブラウザで使うことができるようになっていることも少なくない。
一方で、ブラウザが実装した機能がCSSの標準とならなかったため、あるいは仕様が異なってしまったため、思ったように装飾ができないこともある。

ここではこのような新しい機能について見ていきたい。

グラデーション

現在、linear-gradient()というグラデーションの機能が標準化されつつある。
これは色を指定する場面で使うことができる。
ただし、文字の色は変えられないなどの制限があるので注意が必要である。

CSS
p#bar16 {
  background: linear-gradient(white, gray);
}
p#bar17 {
  background: linear-gradient(to right, #ff0000, #fff);
}
p#bar18 {
  background: linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet);
}
表示例

色を指定

グラデーションの向きと色を指定

グラデーション開始位置と角度、間に入れる色を指定

円形グラデーションは、radial-gradient()を使う。

透明度を指定

透明度を指定するためには2つの方法がある。
予め色を指定する時に透明度を指定しておく方法と、色を指定してあとから透明度を指定する方法である。

色を指定する際に同時に透明度を指定するためには、rgba()を使う。
rgba()はrgb()に透明度を追加したバージョンであり、4つの引数をとる。
1つ目から3つ目までは、0〜255までの赤緑青の値であり、4つ目の引数が透明度で0〜1までの値をとる。

CSS
p#bar19 {
  background-color: rgba(0, 0, 255, 0.7);
}
表示例

alpha=0.9

alpha=0.7

alpha=0.5

alpha=0.3

alpha=0.1

後から透明度を指定するためには、opacityを使う。
opacityはプロパティとして使うことができる。
値は0〜1で、こちらは%表現が使えないので注意が必要である。

CSS
p#bar20 {
	background-color: #00ff00;
	opacity: 0.7 /* 透明度 */;
}	
表示例

0.9

0.7

0.5

0.3

0.1

アニメーション

CSSでアニメーションを実現することもできるようになる予定である。

CSS
div#bar21 {
  animation-name: anime1;
  animation-duration: 5s;
  animation-iteration-count: 10;
}

@keyframes anime1 {
  0% {width: 50px; height: 50px; background-color: aqua;}
  70% {width: 500px; height: 50px; background-color: blue;}
  100% {width: 50px; height: 50px; background-color: aqua;}
}
表示例
animation効果のサンプル
プロパティ 説明
animation-name アニメーション名を指定する
animation-duration アニメーション一回分の時間の長さを指定する
animation-iteration-count アニメーションの繰り返し回数を指定する
animation-delay アニメーションがいつ始まるかを指定する

CSSとJavaScriptからの参照

これまで見てきたように、CSSを使うことによって様々にWebを装飾することができる。
この中にはアニメーションのような動きをもった装飾も含まれていた。
しかし、ここでいう動きをもった装飾は予め決められた動作しかできず、ユーザからの操作などによって動的に動きを変えるものではない。
ここでは、JavaScriptを使うことによって、表示しているページのCSSを動的に変更する方法について学ぶ。

要素の取得

まずは、JavaScriptのプログラムとCSSの関係について説明する。
CSSでは、セレクタを使って装飾する要素を指定し、それに対してプロパティを設定することで様々な装飾をおこなう。
JavaScriptでも基本的には同様で、ある要素を取得し、その要素に対するプロパティを操作する。

JavaScriptで要素を取得する方法については、既に学んだ getElementById()やgetElementsByClassName()、getElementsByTagName()などを使うことができる。
また、DOMのchildNodes[]やfirstChildで要素を取得しても良い。

実際の要素の取得の例を下記に示す。
全ての例において、変数eleに要素が入っている。

getElementById()を使った例
...
var ele = document.getElementById("id1234");
...
getElementsByTagName()を使った例
...
var eles = document.getElementsByTagName("h1");
var ele = eles[0];
...
firstChildを使った例
...
var eles = document.getElementsByTagName("body");
var ele = eles[0].firstChild;
...

スタイルへのアクセス

JavaScriptでHTMLの要素を取得した後は、その要素のstyleプロパティを参照することによって、直接CSSにアクセスできる。
例えば、変数eleに要素が格納されているとすると、ele.styleでCSSにアクセスできる。
具体的には、色にアクセスする場合はCSSのプロパティ名はcolorなので、ele.style.colorとなる。
ただし、「-(マイナス記号)」を含むプロパティ名はそのまま使うことはできず(JavaScriptでは引き算と認識されてしまう)、「-」を削除した上で次の文字を大文字にする必要がある。
例えば、eleに格納されている要素の背景色(background-color)の場合は、ele.style.backgroundColorとなる。
その他の例を下記に示す。

CSS JavaScript
color color
display display
background-color backgroundColor
text-size textSize
text-align textAlign

JavaScriptによるCSSの操作

前節でJavaScriptからCSSを参照する方法について学んだ。
ここでは実際にJavaScriptからCSSを操作する方法を学ぶ。

といっても何も難しいことはなく、JavaScriptからの参照を使って値を代入することによって、スタイルを動的に変更することができる。
次の例を見てほしい。

HTML
<p id="p1234">ここの文字の色が変わります。</p>
<button onclick="changeStyle();">Click Me</button>
CSS
#p1234 {color: red;}
JavaScript
var size = 12;
var color = "red";

function changeStyle() {
  size = size + 1;
  if (color == "red") {
    color = "black";
  } else {
    color = "red";
  }

  var ele = document.getElementById("p1234");
  ele.style.fontSize = size + "px";
  ele.style.color = color;
}

ここの文字の色やフォントサイズが変わります。

この例ではボタンが押されると、changeColor()関数が呼び出される。
changeColor()関数の中では始めのところで、変数sizeの値を1増やしている。
また次のif文では、変数colorの値が”red”の場合は値を”black”に、”black”の場合は”red”にしている。
その上で、要素のstyleを使ってそれぞれ、フォントのサイズと文字の色として設定している。
ここで、フォントサイズには “px” が単位として必要であることに注意が必要である。

練習問題6-

下記のように、文章をクリックすると取り消線が引かれたり、消えたりするプログラムを作成しなさい。

ここをクリックすると取り消し線が引かれたり消えたりする。

練習問題6-

次のようなHTMLがあるとき、cccを含んだ要素、aaaとbbbを含んだ要素の背景色を入力エリアに入力した色に変更するボタンを作成しなさい。
ただし、ボタンを押したときにはまずは初期状態に戻すこと。

<p class="aaa">要素1</p>
<p class="aaa bbb">要素2</p>
<p class="ccc aaa bbb">要素3</p>
<p class="aaa ccc bbb">要素4</p>
<p class="aaa bbb">要素5</p>

要素1

要素2

要素3

要素4

要素5




色:

練習問題6-

下記のように、タブのような動きをするプログラムを作成しなさい。

これはタブ1です。

これはタブ2です。

これはタブ3です。


ヒント1: HTML部は下記のとおりである。

<div class="tabbox">
    <div class="tabs">
        <a class="tab1" onclick="ChangeTab1();">タブ1</a>
        <a class="tab2" onclick="ChangeTab2();">タブ2</a>
        <a class="tab3" onclick="ChangeTab3();">タブ3</a>
    </div>

    <div id="tab1" class="tab tab1">
        <p>これはタブ1です。</p>
    </div>

    <div id="tab2" class="tab tab2">
        <p>これはタブ2です。</p>
    </div>

    <div id="tab3" class="tab tab3">
        <p>これはタブ3です。</p>
    </div>
</div>

ヒント2: タブを横に並べるためには、floatプロパティをleftにする。

ヒント3: タブの上の角を丸くするためには、border-radiusプロパティを適切に設定する。

ヒント4: スタイルでdisplayプロパティをnoneにするとその要素が表示されなくなる。displayプロパティをblockにすると表示される。

ミニプロジェクト


試験

成績評価の項目の1つとして試験を実施します。
成績評価についてを参照してください。
おおよその内容は2011年の試験問題解答用紙を参考にしてください。

最終課題(ミニプロ)

最終課題では、数人でグループを組んで、1つのソフトウェアを開発します。

既にこれまでにプログラミングの基本や、ある程度のWebサービスの活用方法を学んできました。
様々なWebサービスを組み合わせることによって、いろんなプログラムを開発するだけのスキルが身に付いているはずです。
ここでは、復習と腕試しのつもりでプログラムを開発してみましょう。

作成するプログラムは、お遊び的面白いサイト、ゲーム、役に立つツールなど、JavaScriptとWebサービスを使った物であれば何でも構いません。
グループのみんなで相談をしてあっと言わせるようなページを作成してください。

グループの人数等の詳細については、各クラスの教員の指示に従ってください。
クラスによっては1人でソフトウェア開発をする場合もあります。
教員の指示に従ってください。
評価は個人毎に行います。
最終発表の際には、誰がどの部分を担当したのかを明確にして発表をしてください。

グループでプロジェクトを行う場合は、必ず全員がプログラムを作成してください。
「絵を書いた」「HTMLを作成した」といったものは評価しません。
基本的には下記に述べるように関数に分割し、どの関数をだれが担当するのかを決めて作業をしてください。

作成するものは次の指示に従ってください。

  • ミニプロ制作物の最低要件は下記のとおりです。
    • JavaScriptをつかったWebページを作成する。
    • 条件分岐を使う。
    • 繰り返しを使う。
  • また、以下から2つ以上実装してください。
    • 配列または連想配列を使う。
    • センサー情報を使う。
    • マッシュアップを使う。
    • ライブラリを使う。

テーマ設定と設計

ソフトウェアを開発するためには、まず何を作るのかを明確に決定しなければなりません。
どういうサイトを作るかを大雑把に決めたら、まず、サイトのモックアップを作ってみましょう。
HTMLでWebページのデザインだけ先に作ってみるのも良いかもしれません。
その中から詳細な仕様が明らかになっていきますので、それを文書化しましょう。どのようなHTML要素があるのか、そのHTML要素には何が表示されるのか、テキストエリアに文字を入力すると何が起きるのか、ボタンを押すと何が起きるのか、こういったことを明確化していきます。

テキストに文字を入力すると何が起きるのか、ボタンを押すと何が起きるのかを明確化したら、今度はその「何が起きるのか」を詳細化していきます。
ソフトウェア構造の設計に他なりません。
「何がおきるのか」を機能ごとにパーツに分けたり、共通して使えるパーツを抽出したりしていきます。
どのようなWebサービスを使うかもこの段階で明確にしましょう。

プログラムをチームで開発するためには、各パーツパーツのインターフェイスが明確になっている必要があります。
より具体的にはデータ構造や関数の引数などの明確化です。
どのような形でプログラムの中でデータを表現するのか、それは関数呼び出しで渡すのかグローバル変数で渡すのか、サーバサイドプログラミングを使うのか、等です。
また、関数がなにをやってくれる関数なのかを明確にすることも大事です。
add(x, y)という関数が、xの値とyの値を足し算してその結果を返す関数である、と定義すればその中身がどのように実装されていても外から見ると構わない訳です。

ここまでくると、プログラムのどの部分というのを明確に指し示すことができるようになります。
その結果、どこを誰が担当して開発を進めるかを明確に決めることができるようになります。
全体をまとめる部分を担当することになったら、パーツのスケルトン部分(関数の呼び出し部分だけ)を作り、それを使ってプログラミングを進めます。
個々の関数を担当することになった人は、その関数を開発すると同時に、その関数をテストするプログラムを含めて開発を行いましょう。
より大きなプログラムを開発する場合には、プログラムの開発とテストは別の人が担当するのが普通ですが、今回の規模であればそこまでやるには人数が不足しますので、開発者=テスターで良いでしょう。

プログラムの開発

script要素の活用

1つのソフトウェアを複数人のチームで開発するためにはどうすれば良いでしょうか?
基本的には上で述べたようにソフトウェアをパーツパーツに分割して、そのパーツ毎に開発者を決めてプログラム開発を進めて行けば問題ありません。
次に問題となるのは開発したパーツをどのようにして、1つにまとめるかです。JavaScriptの場合にはscript要素を用いることによって、他人が用意したJavaScriptのプログラムを読み込むことができます。
このため、JavaScriptのプログラムを独立したファイルとして用意をしておき、全体をまとめるページからそれを読み込むことによって1つのソフトウェアとしてまとめあげることができます。

独立したページとしてJavaScriptのプログラムを用意するとはどういうことでしょうか?
情報基礎の授業でpublic_htmlディレクトリの下に.htmlで終わるHTMLファイルを作成し、Webページを作成しました。これと同じで、JavaScriptのプログラムもエディタを用いて、独立したファイルとして作成し、public_html下に配置することによって、他のページから読み込めるようになります。
このことを利用して、複数人での開発を独立して進めることができるようになります。

例えば、t00000aaというログイン名の人が自分のpublic_html/JS/sample.jsというファイルにJavaScriptのプログラムを置いた場合、他の人は次のようにしてプログラムを読み込むことができます。

<script type="text/javascript" src="https://web.sfc.keio.ac.jp/~t00000aa/JS/sample.js"></script>

最終発表

授業の最終日には、ミニプロの制作物についての発表会を行います。

発表では、何を作ったかといった表面的なことだけではなく、作成したプログラムの中身について説明をしてください。
フローチャートなどを用いて分かりやすい説明を心がけてください。

また、評価はグループごとではなく、個人ごとにおこないます。
各メンバーが何を担当したのかをきちんと説明してください。

マッシュアップ

目標

JavaScriptの醍醐味の1つは、他人が開発したモジュールを自分のプログラムに組み込んで、大規模なソフトウェアや見栄えのするソフトウェアを開発することである。
ここでは、他人が提供しているサービスを自分のプログラムに組み込んで使うことを学ぶ。

  • マッシュアップの概念を理解する。
  • 他人が用意したサービスを利用する仕組みについて理解する。
  • マッシュアップができるようになる。

Webサービス

この授業で学習する言語としてJavaScriptを選んだ理由の1つには、世の中の人々がWebを介して提供しているサービスを活用できるという点がある。
ライブラリもこの一種であるが、Webサービスはサーバ側で処理をしたり、サーバ側に用意されているデータを使ったりすると言う意味で、ライブラリより高度である。
今回は、Webサービスを使ったマッシュアップについて解説する。
マッシュアップとは、複数の異なる提供元の技術やコンテンツを混ぜあわせて新しいサービスを形作ることである。
すべてを自分で作ると1年以上かかるようなシステムを、短期間で作れてしまうなど、注目されている技術である。
マッシュアップでは、素材となるサービスのプログラム詳細を知る必要がなく、呼び出す手順と、送り返されるデータの形式だけに注目すれば良いため、
自分が作れる以上に複雑なサービスや自分が持っていないデータを使ったサービスを実現できる。

Webサービスの概念

これまで学習してきたように、主としてブラウザ上で動作をする言語である。
このため、JavaScriptのプログラムをブラウザに読み込む事さえ出来れば、プログラムを実行することができる。
もう少し言うと、別の人が作った関数でもブラウザ上に読み込む事ができれば、それを利用することができる。
マッシュアップの場合、読み込んだプログラムはWebサーバ上で提供されるインターフェイスを介して、様々なサービスを提供します。

WebServiceの仕組み

Webサービスを利用するにあたって

Webサービスを利用するにあたってはいくつかの注意が必要である。
ここではそれらの注意点についてみていく。

プログラミング

Webサービスを使うということは、他人のサイトにアクセスすることにほかならない。
このため、無限ループの中でWebサービスを使っていたりすると、他人のサイトに高速に大量のアクセスをすることになる。
たとえプログラムを書いた本人に悪意はなくとも、このような行為はWebサービスを提供している側から見るとDoS攻撃(Denial of Service attack)と見えてしまう。
Webサービスを利用する場合は、Webサービスを提供している側に迷惑をかけないよう、細心の注意を払ってプログラムを作成するように心がけてほしい。

セキュリティ

自分のウェブページに他者のWebサービスを埋め込む場合は、その品質を十分に吟味する必要がある。
悪意を持った他人のWebサービスを埋め込んでしまうと、悪事に加担したことになり、共犯者になってしまう可能性がある。

例えば、見ず知らずの他人から教えてもらったWebサービスを安易に利用してしまうと、表向きは便利な機能でも、
そのWebサービスが個人情報を流出するなど悪意を持った動作をする可能性もある。

このようなトラブルを回避するには、多くの人が長期に渡って利用しているなどの安全性が十分確認されているようなWebサービスを選ぶと良い。

使用条件

Webサービスを利用する場合、「使用条件」を確認し、それを守る必要がある。
たとえば、提供元を明示したり、特定のアイコンを表示することを求められている場合も多くある。
場合によってはユーザ登録が必要なこともある。
近年は多くのサービスがユーザ登録を必要としている。

例えば、友人のホームページのソースの一部をコピーして利用する場合などに、特に注意する必要がある。
サービス呼び出し部分だけでなく、クレジット部分もコピーする必要があるかも知れないし、URLが変ることになるので改めてユーザ登録を行う必要がある場合もある。
対象Webサービス提供者のホームページなどで、使用条件を確認することが重要である。

XMLとJSON

多くのWebサービスでは、XML形式やJSON形式でデータを取得することができる。
ここでは、XMLやJSONについて説明する。

XML

XMLとはExtensible Markup Languageのことで、HTMLのようなMarkup Languageの1つである。
HTML同様に、World Wide Web Consortium (W3C) により策定されている。
XMLは、その名前のとおり、ユーザがタグ群を定義することによって要素を拡張することができ、このため、メタ言語と呼ばれることもある。
基本的には「<タグ名>」で要素の始まりを示し、「</タグ名>」で要素の終わりを示す構造をしている。
現在では、XHTMLKML等、多くのフォーマットがXMLベースで開発されている。

JSON

XMLは柔軟にできており、多くのデータがこの形式で規定されるようになった。
しかし一方で、ファイルサイズが大きくなる、可読性が悪いなどの批判も多くある。
そこで、JavaScriptと親和性のよいJSON (JavaScript Object Notation)というデータ記述方法が登場した。

JSONは、JavaScriptにおけるオブジェクトリテラルをベースとしたデータ記述方法でRFC4627で規定されている。
基本的には、JavaScriptのオブジェクトリテラルを踏襲しているが、数値は10進法表記でなければならない等の制限がある。
また、オブジェクトのキーも文字列で「”」で囲まなければならないことになっている。
以下にJSONで表現されたデータの例を示す。
この例では見やすいように改行を入れてあるが、改行は必ずしも必要ではない。

{
    "name": {
        "familyName": "慶應",
        "firstName": "太郎"
    },
    "age": 19,
    "gender": "male"
}

Webサービスの利用: Google Maps

ここでは、Webサービスの利用の例として、Google Mapsの使い方を学ぶ。

Webサービス

世の中では複雑なWebサービスが提供されている。
これらの多くは、その裏で様々なコンテンツを提供している。
これは、Webサービスが用意している関数(Application Program Interface、APIなどと呼ばれます)を自分が作ったプログラムから呼び出すと、
その関数が必要なサーバと通信を行い、コンテンツを提供する仕組みを取り入れることによって実現している。
下記にその概念を示す。

Webサービスのアーキテクチャ

では実際にコンテンツを提供しているようなWebサービスを利用してみよう。

はじめてのGoogle Maps

下記は良くみかけるGoogle社が提供するGoogle Mapsを貼付けたものである。
このプログラムは実は簡単に実現する事ができる。


上記を実現するプログラムは下記のようになっている。
これまでのプログラムに比べれば幾らかややこしそうに見えるかもしれないが、
1つ1つみていけば、そんなに難しくはない。

HTML部

<div id="map" style="width:300px;height:300px"></div>

<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" type="text/javascript"></script>
<script type="text/javascript" src="mymap.js"></script>

JavaScript部

function initMap() {
  // 地図の中心を決める
  var latlng = new google.maps.LatLng(35.388276, 139.427348);

  // 地図を表示するためのオプションを設定する
  var opt = {
    zoom: 15,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  // 地図を表示する。
  var map = new google.maps.Map(document.getElementById('map'), opt);
}

まず、HTML部の1行目はdivタグを使って地図を表示するエリアを確保している。
ここでは、idとstyleの2つの属性が指定されており、id属性によってIDを「map」に、style属性によってエリアのサイズを幅300px(ピクセル)、高さ300px(ピクセル)に設定している。

3行目はGoogle Maps用のAPIの読み込みである。
Google MapsのAPIはhttps://maps.googleapis.com/maps/api/jsにある。
そこで、Google Maps APIを利用するためにこのプログラムを読み込む必要がある。
この行はHTMLのヘッダにあっても構わない。
むしろヘッダに有る方が普通かもしれない。
ここでは、本来API_KEYを設定しなければならない。
API_KEYはGoogleの「キーの取得、認証」ページから取得できる。
現在のところは、以前のAPIがAPI_KEYを必須としていなかったため、後方互換性に鑑みてAPI_KEYを設定しなくとも動作するようである。
API_KEYを省略するためには、
「<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" type="text/javascript"></script>」の部分から
API_KEYに関する部分をまるごと削除して、
「<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap" type="text/javascript"></script>」のようにする。

また、Google Maps API v3には幾つかのオプションが存在する。
詳しくはGoogle Maps JavaScript API V3 Referenceのページで調べてみてほしい。

HTML部の4行目は、自分が書くべきプログラムファイルであるmymap.jsを読み込んでいる部分である。
Google Maps APIを読み込む際に initMap() をコールバック関数として指定しているため、このプログラムはinitMap()関数を含んでいる必要がある。

では、JavaScriptのプログラムを見てみよう。
まず、3行目では、表示する地図の中心点を決めている。
google.maps.LatLng()で新しいオブジェクトを作っているが、あまり細かいことは気にせず、ここでは引数に緯度と経度を指定して、その結果をlatlngという変数に格納していると思ってほしい。
6行目から10行目は実際に地図を表示する時のパラメータを設定している。
zoomが地図の縮尺を示すもので15に指定されている。
同様に、地図の中心を示すcenterが先ほど生成した変数であるlatlng、地図のタイプを示すmapTypeIdが道路地図(google.maps.MapTypeId.ROADMAP)に設定されている。
そして、それら全体がoptという変数に格納されている。
optがオブジェクトになっていることに気をつけてほしい。
そして13行目がいよいよ地図を表示している部分である。
document.getElementById(‘map’)を使ってWebページにおいて地図を表示すべき場所を特定し、optに設定されたパラメータを使って地図を表示している。

Google Maps APIのより詳しい使い方については、上にもあるが、
Google Maps JavaScript API V3 Referenceのページ
チュートリアルを参照してほしい。

Google Mapsへのイベントリスナ(コールバック関数)の設定

地図を表示すると、その地図を操作した時に何らかの動作をさせたくなる。
これを実現するために、Google Mapsにはイベントリスナを設定する機能がある。
イベントリスナとは、イベントが発生したときに呼び出される関数、コールバック関数のことである。

次のプログラムを見て欲しい。
これは、上の地図を表示させる関数にイベントリスナを追加したものである。
21行目で、clickイベントに対して、click_callback()関数が呼び出されるようにイベントリスナを設定している。
また、16行目から始まるclick_callback()関数がイベントリスナの本体である。
click_callback()は、1つの仮引数を持ち、この変数にイベント発生時の状態が設定されている。
このプログラムでは、17行目で、イベントが発生した場所、つまりクリックされた場所の緯度経度をalert()を使って表示している。
引数にどのような値が返ってくるかは、Google Maps JavaScript API V3 Referenceのページを参照してほしい。
このページの、Eventsの表の”click”のところをみると「Arguments: MouseEvent|IconMouseEvent」と記載されている。
これは、MouseEventオブジェクトかIconMouseEventオブジェクトが設定されて呼び出されるということを意味している。
IconMouseEventオブジェクトは、MouseEventオブジェクトにplaceIdという場所のIDが追加されたものである。
実際、clickイベントから呼び出されるイベントリスナに渡される引数は、通常の地図上をクリックされた時はIconMouseEvent、
ランドマークをクリックされた時はIconMouseEventとなる。

function initMap() {
  // 地図の中心を決める
  var latlng = new google.maps.LatLng(35.388276, 139.427348);

  // 地図を表示するためのオプションを設定する
  var opt = {
    zoom: 15,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  // 地図を表示する。
  var map = new google.maps.Map(document.getElementById('map'), opt);

  // イベントリスナ(コールバック関数)
  function click_callback(e) {
    alert(e.latLng.toString());
  }

  // イベントリスナの設定
  map.addListener('click', click_callback);
}

マーカー

google.maps.Markerクラスを使うことによって、マーカーを設定することができる。
次のプログラムを見て欲しい。
このプログラムでは、16行目でマーカーを作成している。
17行目では、マーカーを置く場所を、18行目ではマーカーを置く地図を指定している。
positionに適当な値を設定することによって、好きな所にマーカーを設定することができる。

function initMap() {
  // 地図の中心を決める
  var latlng = new google.maps.LatLng(35.388276, 139.427348);

  // 地図を表示するためのオプションを設定する
  var opt = {
    zoom: 15,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  // 地図を表示する。
  var map = new google.maps.Map(document.getElementById('map'), opt);

  // マーカーの追加
  var marker = new google.maps.Marker({
                     position: latlng,
                     map: map
		});
}

マーカーにもいろいろなオプションがあるのので、MarkerOptions object specificationを参照してほしい。

JSONPと同一生成元ポリシー

同一生成元ポリシー

JavaScriptには同一生成元ポリシーと呼ばれる制限があり、JavaScriptプログラムをダウンロードしてきたサイト以外のサイトとは通信できないようになっている。
これは、自分が表示したページに置かれていたプログラムが他のサイトに通信を行い、情報が漏洩したりするのを防ぐために存在している制約である。
同じコンテンツでもhttpでアクセスした際とhttpsでアクセスした際で違うドメインと判断されたりするので、注意が必要である。

しかし、プログラムをダウンロードしてきたサイト以外のサイトとは通信ができないという制約は非常に厳しく、JavaScriptの利便性を下げることにつながる。
諸刃の剣である。

同一生成元ポリシーの回避: JSONP

同一生成元ポリシーは、JavaScriptプログラムからはプログラムを持ってきたサイトのみにしかアクセスできないというものである。
逆に言えば、アクセスしたいサイト、つまりデータがあるサイトにアクセスのためのJavaScriptプログラムがあればアクセスに何も問題はないということになる。
このことを利用して、JSONを処理する関数を予め自分で用意しておき、データを持っているサイト側から用意した関数を呼び出してもらうことで同一生成元ポリシーを回避することができる。

例えば次のようなプログラムがあったとする。
ここで9行目以降が別のサイトにあって、そのサイトにあるデータを引数にしてメソッドを呼び出してくれると考えてほしい。
この例では、2行目が実行されると、10行目の関数process()が呼び出される。
すると、関数process()からは、引数にデータが格納された状態で自分で定義した関数であるfunc()が呼び出される。
こうすることによって、他のドメイン上におかれているデータを自分の定義した関数で受け取ることができる。

// 他のドメインにあるべき関数の呼び出し(読み込み)
process();

// 自分で定義した関数
function func(json) {
  alert(json.a + " + " + json.b + " = " + (json.a + json.b));
}

// 他のドメインにあるべき関数
function process() {
  func({ "a": 123, "b": 456 });
}

実際には次のようにして用いる。
この例では、MediaWiki APIのQuery APIを用いて、
WikiPediaに登録されている「慶應」で始まる言葉をリストアップし、上位50位を表示している。
「<script src=”http://ja.wikipedia.org/w/api.php?action=query&list=allpages&apfrom=慶應& aplimit=50&format=json&callback=func”>」の部分で、
実際には上で述べた様なデータを引数とした関数が返ってくるので、ここでfunc()が呼び出される。
このように別のプログラムから呼び出される関数のことをコールバック関数と呼ぶ。
コールバック関数の渡し方は、使うWebサービスによって異なりますので、Webサービスのマニュアルを参照してほしい。

JavaScript部

function func(json) {
  var ele = document.getElementById("listOfKeio");

  var i;
  for (i=0; i < json.query.allpages.length; i++) {
    ele.innerHTML += (i + ": " + json.query.allpages[i].title + "<br />");
  }
}

HTML部

<div id="listOfKeio"></div>
<script src="myprog.js"></script>
<script src="http://ja.wikipedia.org/w/api.php?action=query&list=allpages&apfrom=慶應&aplimit=50&format=json&callback=func"></script>

しかし、この方法を使ってWebサービスを利用するためには大きな問題がある。
script要素でWebサービスのページ、つまりWikipediaのページにアクセスしたタイミングでしかcallback関数を呼び出すことができない点である。
これでは必要なタイミングにデータを取ってくることが出来ない。

そこで、JSONPを利用する場合は次のように、プログラムの中でscript要素を生成する。
JavaScript部の12行目ではscript要素を新たに生成し、変数oに代入している。
createElement()は、新たにHTML要素を作り出すためのメソッドである。
また、13行目ではsetAttribute()メソッドを使ってsrcアトリビュートを12行目で生成したscript要素に追加している。
その後、14行目において、生成したscript要素をdiv要素の子供として、つまりdiv要素の中に設定している。
このことによって、script要素が表示されたタイミング(実際には目には見えないがHTML文書の中には埋め込まれている)、
つまりボタンが押されたタイミングでコールバック関数func()が呼び出され、「慶應」で始まる言葉をリストアップしている。

HTML部

<script type="text/javascript" src="myprog.js"></script>

<button id="listKeio" onclick="getFromWikipedia()">List</button>
<div id="listOfKeio"></div>

JavaScript部

function func(json) {
  var ele = document.getElementById('listOfKeio');

  var i;
  for (i=0; i < json.query.allpages.length; i++) {
    ele.innerHTML += i + ": " + json.query.allpages[i].title + "<br />";
  }
}

function getFromWikipedia() {
  var e = document.getElementById('listOfKeio');
  var o = document.createElement("script");
      o.setAttribute("src", "http://ja.wikipedia.org/w/api.php?action=query&list=allpages&apfrom=慶應&aplimit=50&format=json&callback=func");
  e.appendChild(o);
}

練習問題11-

上の説明を参考に、Google Mapを表示するプログラムを作成しなさい。

練習問題11-

上の説明を参考に、Google Mapを表示し、地図上をクリックすると、その場所の緯度経度が表示されるプログラムを作成しなさい。

注意: https://maps.googleapis.com/maps/api/js を同じページで複数回呼び出すことはできない。
そのため、他の練習問題と同一ページに作成する場合は、コールバック関数を1つにまとめる必要があるので注意が必要である。

練習問題11-

上の説明を参考に、Google Mapを表示し、地図上をクリックすると、その場所を中心とした地図が表示されるようにしなさい。
地図の中心点を変える場合は、地図オブジェクトのsetCenter()メソッドを使う。
例えば、地図オブジェクトが変数mapに入っている場合は、map.setCenter(lonlat)のようにする。
ただしここで、lonlatは緯度経度が入ったオブジェクトである。

注意: https://maps.googleapis.com/maps/api/js を同じページで複数回呼び出すことはできない。
そのため、他の練習問題と同一ページに作成する場合は、コールバック関数を1つにまとめる必要があるので注意が必要である。

練習問題11-

上の説明を参考に、Google Mapを表示し、地図上をクリックすると、その場所にマーカが設置されるようなプログラムを作成しなさい。
また、その際に、マーカーに”1″, “2”, “3”とラベルが設定されるようにしなさい。
このさい、Markerオブジェクトを生成する際のlabelプロパティの値の指定は文字列でなければならないことに注意すること。

注意: https://maps.googleapis.com/maps/api/js を同じページで複数回呼び出すことはできない。
そのため、他の練習問題と同一ページに作成する場合は、コールバック関数を1つにまとめる必要があるので注意が必要である。

練習問題11-

上の説明を参考に、ボタンを押すと慶應に関連する言葉が50個表示されるプログラムを作成しなさい。

ライブラリ

目標

JavaScriptの醍醐味の1つは、他人が開発したモジュールを自分のプログラムに組み込んで、大規模なソフトウェアや見栄えのするソフトウェアを開発することである。
ここでは、他人が提供しているライブラリを自分のプログラムに組み込んで使うことを学ぶ。

  • ライブラリの概念を理解する。
  • 他人が用意したライブラリを利用する仕組みについて理解する。
  • jQueryのようなライブラリが活用できるようになる。

JQuery

jQueryの基本

jQueryとは

JavaScriptの基本はHTMLで記述されたページに動きを与えることである。
ボタンを押すことによって動作を加えたり、フォームに入力した値によってページに表示されている内容を変更したりできる。
しかし、複雑なことをしようとすればするほど、面倒な手続きが多く出てくる。
そこで、JavaScriptをより簡単に使えるようにするために、ライブラリが開発されるようになった。
ライブラリとは、再利用可能な汎用性のある機能をまとめてパッケージ化したものである。

JavaScriptでは、多くの人々が様々なライブラリを開発し、公開している。
ここでは、その中でも良く利用されるjQueryについて紹介する。

jQueryは2006年に開発・公開されたJavaScriptライブラリで、CSSに近い記述方法を採用しているのが特徴である。
jQueryを使うことによって、短いコードでHTMLを操作することが可能になる。

それでは早速、jQueryを使ってみよう。

jQueryの使い方

jQueryを使うためには、jQueryライブラリをjQueryのサイトからダウンロードし、
これを自分のサイトに配置して、script要素を使って読み込む必要がある。
jQueryのサイトでは、Minifiedと呼ばれる圧縮された形のライブラリと、Uncompressedと呼ばれる圧縮前のライブラリが提供されている。
これら二つの機能は同じだが、通常はMinifiedを利用する。
これは、変数名を短くしたり、コメントを省くなどの手法を使ってファイルサイズを小さく押さえてあるため、
ダウンロードが早く終わるためである。
一方で、Minifiedライブラリは人間が読むには不向きで、jQueryのコードそのものに興味がある場合は、
Uncompressedライブラリをダウンロードした方が良い。

本来は自分でダウンロードして、コードを自分のサイトに配置するが、
本授業では予めMinifiedライブラリをhttps://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.jsに、
Uncompressedライブラリをhttps://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.jsに配置してあるので、これを利用する。
それぞれのリンクをクリックして表示してみると、MinifiedライブラリとUncompressedライブラリの違いがわかる。

初めてのjQuery

なにはともあれ、jQueryを使ってみよう。
次のプログラムを見てほしい。

<ul>
<li>Hello World!</li>
<li>Hello SFC!</li>
</ul>

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function(){
  $("li").css("color", "red");
});
</script>

このプログラムの実行結果は下記のようになる。

  • Hello World!
  • Hello SFC!


プログラムでは、1つめのscript要素でhttps://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.jsを読み込んでいる。
また、2つめのscript要素は、これまで学習してきたJavaScriptとは全く異なる。
この2つめのscript要素の中に書かれたものがjQueryを使ったプログラムである。

jQueryでは、HTMLのどの部分を操作するかを指定し、その上で操作する内容を書くことが基本となる。
操作する部分を指定するものをセレクタと呼ぶ。
CSSのセレクタと同じである。
上記のプログラムにおいては、9行目の「$(…)」で囲まれた「”li”」の部分がセレクタである。
この例では全てのli要素を指定している。
CSSのセレクタと同じ表現で、クラスやIDなどを指定することもできる。
その上で、jQueryの操作の部分が「css(“color”, “red”)」となる。
これは、文字の色を赤に指定している。
結果として、箇条書きの部分が全て赤く表示されることになる。

8行目の「$(function(){」と10行目の「});」は何であろうか?
これは、jQueryの命令が実行されるタイミングを指定している部分である。
正確には「$(document).ready(function(){」と「});」するが、省略形として「$(function(){」と「});」が使われる。
非省略形をみると解るが、この記述方法は、ドキュメントの準備ができたら実行する、ということを示している。
つまりページの読み込みが終わった時点で、その中身(今回のプログラムでは「$(“li”).css(“color”, “red”);」)が実行れる。
多くの場合HTMLが全て読み込まれてから処理を始めたいため、
このように「$(function(){」と「});」で囲まれた部分にプログラムが記述されることが多い。

まとめると、次のような書き方が基本になる。

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function(){
  jQueryのプログラム
});
</script>

さて、多くの場合「$(function(){」と「});」で囲まれた部分にプログラムが記述されると述べたが、
イベントドリブンでプログラムを動かす場合等はこの限りではない。
例えば次のプログラムを見てほしい。
こちらの方が親しみがあるかもしれません。

<div id="helloworld">Hello World!</div>
<button onclick="changeColor()">Click me!</button>

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
function changeColor() {
  $("#helloworld").css("color", "red");
}
</script>

このプログラムを実行した結果は下記のようになる。
ボタンを押してみてほしい。
「Hello World!」と表示されている部分の色が変わっただろう。
つまり、これまでgetElementById()等を駆使して行ってきた操作をjQueryを使うことによって、短く簡単に記述している。

Hello World!


ここでJQueryのセレクタとしては、新しく「#helloworld」が出てきた。
jQueryでは、文字列の前に「#」をつけると、id属性を指定することになります。
なにも付けないときは要素を、「#」を付けるとid属性を指定することになる。
これは先にも述べたとおり、CSSのセレクタの指定と同じである。

セレクタ

上で見てきたように、jQueryを使いこなすためにはセレクタを使いこなす必要がある。
ここではセレクタの指定の仕方をより詳しく見てく。

要素セレクタ

要素セレクタは、上記でも説明した通り特定の要素を指定するためのセレクタである。
指定した要素が複数存在すると、その全部が対象となる。
記述方法は、単に要素名を指定するだけである。

IDセレクタ

IDセレクタは、要素につけらているid属性を指定するためのものである。
1つのページには同じid属性をもつ要素は存在してはいけないので、この指定方法を使うと、特定の1つの要素のみを指定することが出来る。
記述方法は、id属性名の前に「#」をつける。
要素セレクタとIDセレクタをつなげて「$(“div#helloworld”)」のように書くこともできる。
ただしここで、「div」は要素名、「helloworld」はid属性の値である。

クラスセレクタ

クラスセレクタは、要素につけらているclass属性を指定するためのものである。
指定したクラスが複数存在すると、その全部が対象となる。
記述方法は、class属性名の前に「.」をつける。
要素セレクタとIDセレクタをつなげて「$(“div.article”)」のように書くこともできる。
ただしここで、「div」は要素名、「article」はclass属性の値である。

子孫セレクタ

子孫セレクタは、ある要素の更に内側にある要素を絞り込むためのものである。
例えば「子孫セレクタは子孫を指定するためのものである。」という文章があり、div要素の中にあるstrong要素、つまり「子孫セレクタ」の部分を指定するような場合に使う。
記述方法は、親要素と子孫要素をスペースで区切って連続して書く。
例えば「$(“div strong”)」のように記述する。
必ずしも要素名である必要はなく、「$(“.article strong”)」のような指定も可能である。

ユニバーサルセレクタ

ユニバーサルセレクタは、全ての要素を選択するためのものである。
ユニバーサルセレクタを指定するためには「*(アスタリスク)」を使う。
例えば、div要素の中の全ての要素を指定するためには、「$(“div *”)」のように記述する。

複数のセレクタ(or)

複数のセレクタのうちどれかに合致すればよいというタイプの指定手法である。
複数のセレクタを並列に指定するためには「,」で区切る。
例えば「$(“#question1,#question2”)」のように指定する。

複数のセレクタ(and)

複数のセレクタのうち全てに合致するものを指定する手法である。
複数のセレクタを区切らずに並べる。
例えばクラスの場合、「$(“.class1.class2”)」のように指定する。
「+」を使って「$(“.class1″+”.class2″)」のように指定するとわかりやすい。

その他のセレクタ

上で紹介した以外にも、jQueryには様々なセレクタが存在する。
より詳しいことはjQueryのドキュメントのセレクタの章を参照してほしい。

<ul>
<li id="campus1" class="tokyo">信濃町</li>
<li id="campus2" class="tokyo">芝共立</li>
<li id="campus3" class="kanagawa">湘南藤沢</li>
<li id="campus4" class="kanagawa">日吉</li>
<li id="campus5" class="tokyo">三田</li>
<li id="campus6" class="kanagawa">矢上</li>
</ul>
<button onclick="reset()">リセット</button><br />
<button onclick="tokyo()">東京</button>
<button onclick="kanagawa()">神奈川</button><br />
<button onclick="campus1()">信濃町</button>
<button onclick="campus2()">芝共立</button>
<button onclick="campus3()">湘南藤沢</button>
<button onclick="campus4()">日吉</button>
<button onclick="campus5()">三田</button>
<button onclick="campus6()">矢上</button>
  • 信濃町
  • 芝共立
  • 湘南藤沢
  • 日吉
  • 三田
  • 矢上


jQueryによる文書の操作

jQueryを使うことによって、文書を構成しているHTMLやCSSを操作することができる。
ここでは文書の操作について説明する。

CSSの制御

前の章でも見てきたように、jQueryを使うことによってCSSを動的に操作することが出来る。
CSSを操作するためにはcss()を使う。
css()の書式は「css(プロパティ名, 値)」となっている。
ここでプロパティ名は「”color”」や「”background-color”」のようなプロパティ名、
値はそのプロパティに設定する値の文字列となる。

複数のプロパティを同時に変更することも可能である。
例えば文字の色と背景色を同時に変更するためには次のようにする。
この時、プロパティ名はCSSのそれとは異なり、JavaScriptでCSSを指定する際に使われるプロパティ名である。
つまり、CSSのプロパティ名で「background-color」のように「-」でつながれているものの場合は、「-」を削除し、
次の頭文字を大文字にする。

$("div").css({
  backgroundColor: "red",
  color: "blue"
});

プログラムではCSSのプロパティの値を知りたい場合もある。
このような場合にもcss()を使う。
ただし、プロパティを設定する場合と書式が異なり、「css(プロパティ名)」となる。

<div id="weather">晴れ</div>

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
document.write("色は" + $("#weather").css("color") + "です。");
</script>

例えば上のプログラムを実行すると、下のような結果になる。
ここで「rgb(51,51,51)」となっているのが色である。
実際には、ページに指定されているCSSによって表示される色は異なる。
それぞれの値は赤、緑、青を示しており、0〜255の値をとる。

HTMLの操作

これまでにinnerHTML()を用いて、HTML要素の中身を書き換えてきた。
jQueryでも同じ機能を提供している。
jQueryでHTML要素の中身を書き換えるためには「html()」を使う。
使用方法は簡単で、次のようにする。

<div id="weather">晴れ</div>
<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$("#weather").html("<strong>雨</strong>時々<strong>曇り</strong>");
</script>

この例では、もともとHTMLによって「晴れ」と表示されるはずだった部分を、
時々曇り」に置き換えている。

html()でも、値の取得が可能である。
引数を空にすることによって要素の中のHTML部分を取得することができる。

HTML要素の挿入、移動

jQueryを使うことによって、HTML要素の挿入や移動を行うことができる。
下記の表にまとめる。

メソッド 説明
sel1.prepend(sel2) sel1で指定された要素の中の先頭に、sel2で指定された要素を移動する。
sel1.append(sel2) sel1で指定された要素の中の末尾に、sel2で指定された要素を移動する。
sel1.before(sel2) sel1で指定された要素の直前に、sel2で指定された要素を移動する。
sel1.after(sel2) sel1で指定された要素の直後に、sel2で指定された要素を移動する。

メソッドは、sel1 を値として返す。
上記で、sel2 のところに $(“<div>1</div>”) または、”<div>1</div>” などのように、html を書くこともできる。
(html を書く場合は、新規生成+移動なので、挿入というイメージになる)

メソッド 説明
prependTo(sel) selで指定されたセレクタで選択した要素の先頭に、メソッドを指定した要素を移動する。
appendTo(sel) selで指定されたセレクタで選択した要素の最後に、メソッドを指定した要素を移動する。
insertBefore(sel) selで指定されたセレクタで選択した要素の前に、メソッドを指定した要素を移動する。
insertAfter(sel) selで指定されたセレクタで選択した要素の後に、メソッドを指定した要素を移動する。

メソッドは、移動後の要素を値として返す。
上記で、sel2 のところに、$(“<div>1</div>”) などのように、html を書くこともできる。
(html を書く場合は、新規生成+移動なので、挿入というイメージになる)

より詳しくはjQueryのドキュメントの操作の章を参照してほしい。
他にも沢山の操作のためのメソッドが用意されている。

フォームからの値の取得

これまでのプログラムでは、フォーム、特にテキストエリアからの値の入力を多用してきた。
このような値の入力についてもjQueryは簡単なインターフェイスを提供している。
例えば、下記は初期の頃に使った例で、名前を入力すると「こんにちは○○さん」と表示されたアラートが出るというものである。

<script type="text/javascript">
function hello(){
  // テキスト要素を特定する
  var name = document.getElementById("text1");

  // アラートを表示する。
  alert("こんにちは、" + name.value + "さん");
}
</script>

<form>
お名前をどうぞ: <input id="text1" type="text" size="20"><input type="button" value="OK" onclick="hello()"> 
</form>

これをjQueryを使って書き直すと次のようになる。
「val()」を用いることによって、簡単にinput要素の値を取得することができる。

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
function hello(){
  // アラートを表示する。
  alert("こんにちは、" + $("input#text1").val() + "さん");
}
</script>
 
<form>
お名前をどうぞ: <input id="text1" type="text" size="20"><input type="button" value="OK" onclick="hello()">
</form>

また、val()を使って値をセットすることもできる。
値をセットする場合は「val(値)」と書く。
例えば次のようにする。

$("input#text1").val("佐藤");

メソッドチェーン

1つの要素に対して複数のメソッドを順に適用したい場合、
jQueryではメソッドチェーンというインターフェイスを用意する。
例えば、次に示すように1つの要素に3つの操作をしたいとする。

<div id="soup">付け</div>

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$("div#soup").prepend("御");
$("div#soup").prepend("御");
$("div#soup").prepend("お");
</script>

この場合、3つの操作をまとめて次のように書くことができる。

<div id="soup">付け</div>

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$("div#soup").prepend("御").prepend("御").prepend("お");
</script>

もちろん、異なるメソッドが混じっていても問題ない。

jQueryによるイベントモデル

jQueryはイベントモデルに対してもインターフェイスを提供している。
ここでは、jQueryを用いたイベントハンドリングの手法を説明する。

ready()再び

一番始めに、jQueryのプログラムは「$(function(){」と「});」の間に書かれることが多いと説明した。
しかし、ここまでこのような例は殆ど出てきていない。
ここでは、「$(function(){」と「});」の意味について少し詳しく説明する。

「$(function(){」〜「});」は前にも述べた通り「$(document).ready(function(){」〜「});」の省略形である。
それでは「$(document).ready(function(){」〜「});」とはいったいなんなのだろう?
jQueryの使い方では、これまで「要素の選択.メソッド」という形をとってきた。
しかし、実はjQueryはその外側にイベントを定義することが出来る。
これが「$(document).ready(function(){」〜「});」の正体である。
「$(document).ready(function(){」〜「});」は「$(document)」、
つまりドキュメント全体に対して「ready()」のイベントが発生した時に実行する、という意味である。
「ready()」イベントはドキュメントが全て読み込まれた時に発生するため、
「$(document).ready(function(){」〜「});」は結論としてページが全て表示された状態になった直後に実行される。
つまり、ページを読み込んでいる途中ではなく、
ページを読み込み終わった後にプログラムを実行する際には「$(document).ready(function(){」〜「});」が使える。

click()とイベントハンドリングの基本

さて、「$(document).ready(function(){」〜「});」のおまじないが理解できたところで、別のイベントについて見てみよう。

まずは、一番基本のイベント、click()である。
click()は名前の通り、要素がクリックされた際に発生するイベントをハンドリングするためのものである。

次のプログラムを見てほしい。
このプログラムでは、1行目のHTML部分でボタンを1つ作っている。
しかし、これまでのようにonclick属性をつかって関数をひもづけていない。
その代わりにJavaScriptのプログラムの方でjQueryを使って「$(“button”).click(function(){」〜「});」で、
イベントハンドラを定義している。
「$(“button”).click()」は、button要素でクリックイベントが発生したら、という意味である。
クリックイベントが発生した際には、関数の内側、つまり中括弧で囲まれた部分が実行される。

<button>Click me</button>

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$("button").click(function(){
  alert("Click!!");
});
</script>

しかし、ここで落とし穴がある。
プログラムを次のように変更してみよう。
プログラムは動かなくなる。
これは、プログラムが読み込まれる、つまり実行される時にbutton要素が存在していないためである。

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$("button").click(function(){
  alert("Click!!");
});
</script>

<button>Click me</button>

これを回避するためにはどうすれば良いのでだろうか?
ここでいよいよ「$(function(){」〜「});」の出番である。
「$(function(){」〜「});」はドキュメントが全て読み込まれた時に実行されるので、
この中にイベントハンドラを定義する部分も入れ込んでしまえば良いのである。
具体的には次のようになる。
これによって、「$(“button”).click()」の部分が、ページが読み込まれた後に実行されるようになり、
結果としてbutton要素をハンドリングできるようになる。

<script type="text/javascript" src="https://ipl.sfc.keio.ac.jp/text/info2-2018-9/lib/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function() {
  $("button").click(function(){
    alert("Click!!");
  });
});
</script>

<button>Click me</button>

様々なイベント

jQueryでは、イベントをハンドリングするためのメソッドも沢山用意されている。
主なものを以下にまとめておく。
より詳しくは、jQueryのドキュメントのイベントの章を参照してほしい。

メソッド 説明
click() 要素がマウスでクリックされる。
dblclick() 要素がマウスでダブルクリックされる。
mousedown() 要素の上でマウスが押下される。
mouseup() 要素の上で押下されたマウスが放される。
mouseover() 要素の上にマウスが重ねられる。
mouseout() 要素の上に重ねられたマウスが外れる。
focus() input要素などが選択され入力状態になる。
blur() input要素などが選択が解除される。
change() input要素などの値が変化する。

その他のライブラリ

先にも述べたとおり、JavaScriptで使える多くのライブラリが公開されている。
例えば次のようなものはグラフを描いたり、図を描いたりするのに非常に有用なので参考にしてほしい。

  • ChartJS[奈良先生資料]
  • 棒グラフ、折れ線グラフ、レーダチャートなどのグラフを描画するためのライブラリ。仕様に従ったデータを用意することにより、容易にグラフを描くことができる。

  • D3[奈良先生資料]
  • D3はデータに基づいて、描画するためのライブラリである。非常に高機能であり様々なことができるが、使い方が少々複雑。

  • Tone.js[奈良先生資料]
  • Webで音を鳴らすことができるAPIであるWeb Audio APIを簡単に利用するためのライブラリ。

練習問題10-

下記のように、文章をクリックすると取り消線が引かれたり、消えたりするプログラムをjQueryを使って作成しなさい。

ここをクリックすると取り消し線が引かれたり消えたりする。

練習問題10-

次のようなHTMLがあるとき、cccを含んだ要素、aaaとbbbを含んだ要素の背景色を入力エリアに入力した色に変更するボタンをjQueryを使って作成しなさい。
ただし、ボタンを押したときにはまずは初期状態に戻すこと。

<p class="aaa">要素1</p>
<p class="aaa bbb">要素2</p>
<p class="ccc aaa bbb">要素3</p>
<p class="aaa ccc bbb">要素4</p>
<p class="aaa bbb">要素5</p>

要素1

要素2

要素3

要素4

要素5




色:

練習問題10-

次のようなもぐらたたきゲームをjQueryを使って作成しなさい。

0匹目


関数と引数、センサー

目標

これまでにもイベントが起きた時に実行されるイベントハンドラとして関数を扱ってきた。
ここでは、より複雑な関数について学ぶ。

  • 関数の概念について理解する。
  • 引数を使った関数の作成や、呼び出しができるようになる。
  • 他人が作った関数を呼び出せるようになる。
  • コールバック関数の概念について理解する。
  • センサー情報を取得するためのコールバック関数開発ができるようになる。

関数と引数

関数では、関数を呼び出す際に値を渡すことができる。
引数として関数に渡した値は、引数に記述した変数に代入されて、関数内で参照することができる。
この時、普通の変数を新しく定義する時のように、varはつけない。

JavaScript
function sum(num1, num2){
    alert(num1 + num2);
}

sum(20, 15);
// 35がアラート出力される

上の例では、5行目のsum()関数の呼び出しにより、20と15という数字がsum()関数にわたされる。
このような値のことを引数と呼ぶ。
実際のsum()関数は1行目から3行目で定義されている。
1行目の括弧の中には、num1およびnum2という変数が指定されている。
これは、関数呼び出しの際の引数を受けるための変数で、仮引数と呼ばれる。
関数は呼び出されると、仮引数で指定されている変数に値が入った状態で動作する。
つまり上の例では、2行目のalert()によって、num1+num2の計算結果、つまり35がアラートで表示されることとなる。

関数、仮引数、返り値の概念をより直感的にわかるように下記の図に示す。
左のプログラムの中の緑の部分が、右の関数に展開されるような形で実行される。
この例では、引数にか加えて返り値が導入されている。

関数呼び出し

この例では、add()という関数を定義して使っている。
add()という関数は、仮引数としてxとyの二つを持っている。
関数の中では、この二つの変数を足し算をして別の変数zに格納し、そのzをreturn文を使ってもとのプログラムに返している。
呼び出しもとのプログラムの方をみてみよう。
aという変数を定義して、それを2で初期化している。
その次の行では、変数sumを定義している。
次の代入文のところでadd()という関数が出てくる。
add()関数を呼び出すにあたって、引数に1という値とaという変数が指定されている。
関数を呼び出すと制御が一旦関数側に移るが、この際、引数に指定された値が関数の仮引数にセットされる。
この例の場合は、xに数値である1が、yにはaの中の値である2がセットさる。
このため、add()関数の中のz=x+yが実行されるときには、xが1、yが2になっており、zは3となる。
その後、add()関数の中の最後の行であるreturn文によって、関数が最終的に呼び出し側のプログラムに返す値がzであることが示されている。
この値のことを返り値と呼ぶ。
このため、呼び出し側ではadd(1, a)の評価結果は3となり、結果として変数sumに3が代入される。

JavaScript
// add()関数の定義
function add(x, y) {
    var z = x + y;
    return z;
}

// 呼び出し側のプログラム
function lec01_02_click() {
    var a = 2;
    var sum;

    sum = add(1, a);

    alert('sum = ' + sum);
}

コールバック関数

JavaScriptはすべての値は「オブジェクト」として表現されるため、どんなものでも同じ変数の中にいれることができる。
そのため、関数を呼び出す際に関数も引数として渡すことができる。
このことを活用して、関数を引数として登録しておき、処理が終わった、センサーの値が変わったなどの何らかのイベントでその関数が呼び出されるような仕組みを実現することができる。
このようなイベントに備えて登録される関数を、コールバック関数(callback function)と呼ぶ。
具体的な例については、次章以降のセンサーの使い方の部分を参照してほしい。

Ambient Light Events

World Wide Webコンソーシアム(W3C)のDevice APIs Working Groupでは、多くのセンサー情報を使うためのAPIを標準化している。
その中に、iMacでも使えるものとして照度センサーがある。
ここで使ってみよう。

次のプログラムを見てほしい。
HTML部では、テキストエリアを作成し、その後ろに「lux」という単位を表示している。
luxは照度を表す単位である。
JavaScript部では、始めにlight_print()という関数を定義している。
この関数は、照度に変化があった時に呼び出されるコールバック関数である。
照度が変化した時に呼び出される関数は1つの引数を取ることがAPIで決められているため、その引数を仮引数eventで受けている。
2行目から3行目はそれぞれ、テキストエリアを取得し、そのテキストエリアに実際の照度の値を設定している。
6行目はプログラムが読み込まれたときに実行される部分である。
ここで、'devicelight'は照度センサーを表している。
照度センサーの値に変化があると、第2引数で設定されている関数であるlight_print()が呼び出される。
1度設定しておくと、値に変化があるたびにこの関数が呼び出されることに注意してほしい。

HTML
<input type="text" id="lighttext" value="照度を変化させてくだい"> lux
JavaScript
function light_print(event) {
	var elm = document.getElementById('lighttext');
	elm.value = event.value;
}

window.addEventListener('devicelight', light_print);
表示例
lux

iMacの照度センサーはカメラの横にある。
カメラの部分に手をかざしたり、離したりすると照度センサーの検知する値が変化する。

最近のFirefoxで照度センサーを使うためには、
ブラウザで「about:config」を開き(アドレスバーに「about:config」と入力してください。警告が出る場合ありますが、そのまま進んでください。)、
device.sensors.ambientLight.enabled の値を true にする必要があります。
値を true にするためにはdevice.sensors.ambientLight.enabledの行をダブルクリックしてください。
JavaScriptにおけるセンサー情報の利用はまだまだ発展途上段階です。
多くのスマートフォンでは既にサポートしていたりしますが、固定のPCではたとえセンサーを内蔵していても、JavaScriptからは使えないことも多いようです。
また、ブラウザによっても使える機能が異なったりします。
実際、照度センサーはFirefoxでは使えますが、Mac OS XのSafariでは使えません。

タイマー

センサー情報等を使いはじめると、定期的に処理したくなることがある。
ここでは、JavaScriptにおけるタイマーの使い方について学ぶ。

JavaScriptでは、指定時間後に指定した関数を呼び出すタイプのタイマーと、定期的に指定した関数を呼び出すタイプのタイマーの2種類が使える。
前者は、1回関数が呼び出されると、それで終了となる。
後者は、例えば3秒毎に何度でも繰り返し関数が呼び出されることとなる。

次のプログラムを見て欲しい。
このプログラムでは、始めにtimeout_callback()というコールバック関数を定義している。
この関数が呼び出されるとアラートが表示される。
また、5行目では10000ms後(10秒後)にtimeout_callback()を呼び出すように設定している。
このため、このプログラムを実行すると、10秒後に「timeout!」と書かれたアラームが表示される。

JavaScript
function timeout_callback() {
  alert("timeout!");
}

setTimeout(timeout_callback,10000);

また、似たプログラムだが、次のプログラムはすこし違う動作をする。
上のプログラムとの違いは、5行目がsetTimeout()ではなく、setInterval()になっているところのみである。
こちらのプログラムでは、上と異なり、10秒毎にtimeout_callback()が呼び出され、結果的に10秒毎にアラートが表示される。

JavaScript
function timeout_callback() {
  alert("timeout!");
}

setInterval(timeout_callback,10000);

また、繰り返し呼び出されるタイマーを、開始したり停止したりするためには、タイマーを指定する必要がある。
setTimeout()関数やsetInterval()関数は呼び出されるとタイマーオブジェクトを返すので、それを変数に記憶しておくことにより、
タイマーを停止させたりすることができる。

次のプログラムでは、setInterval()が返す値を変数timerに記憶しておくことによって、
タイマーを開始したり止めたりすることができるようになっている。
setInterval()の中にあるtimeout_callbackは、タイムアウトした時に呼び出される関数の名前である。

HTML
<button onclick="startTimer()">Start</button>
<button onclick="stopTimer()">Stop</button>
JavaScript
var timer = null;

function startTimer() {
    if (timer == null)
        timer = setInterval(timeout_callback, 3000);
}

function stopTimer() {
    if (timer != null)
        clearInterval(timer);
    timer = null;
}

練習問題9-

次のように、曜日と時限を引数として呼び出すと、その時間帯に履修している科目名が返るような関数を作成しなさい。
ただし、何も履修していない曜日時限が入力された場合は、「履修している科目はありません。」と返すものとする。

...
var week = "mon";
var period = 1;
var title = classTitle(week, period);
...

また、2つのテキストエリアと1つのボタンをつくり、それぞれのテキストエリアに曜日と時限を入力してボタンを押すと、
作成した関数を使って履修している科目名を取得し、その科目名をアラートで表示するようなページを完成させなさい。

ヒント: 関数側にデータをもたせます。

練習問題9-

上の例で示した、照度の変化によって下記のように照度の値が変化するWebページを作成しなさい。

lux

練習問題9-

次のように照度が変化すると棒グラフが動くようなプログラムを作成しなさい。

棒グラフ

練習問題9-

スタートボタンを押してから10秒後に1回だけ「timeout!」とアラートで表示するプログラムを作成しなさい。

練習問題9-

スタートボタンを押してからから10秒毎に「timeout!」とアラートで表示するプログラムを、setInterval()を使って作成しなさい。
また、ストップボタンを押すと止まるようにしなさい。

練習問題9-

テキストエリアから文字列を入力してボタンを押すと、その文字列をページ内に予め用意したp要素内に1秒ごとに1文字ずつ表示するプログラムを作成しなさい。
例えば、テキストエリアに「keio」と入力されてボタンが押された場合、
1秒目に「k」、2秒目に「ke」、3秒目に「kei」、4秒目に「keio」とp要素に表示される。

ヒント: 文字列のn文字目を取り出すためには、charAt()を使います。使い方は自分で調べてみましょう。

練習問題9-

次のような、照度センサーの値を示した棒グラフが1秒ごとに横に流れていくプログラムを作成しなさい。

棒グラフ

配列と連想配列

目標

多くのプログラミング言語は配列などのデータ構造を持つ。
JavaScriptも例外ではなく、配列などのデータ構造を持っている。
ここでは、JavaScriptが持つこれらのデータ構造について学ぶ。

  • 配列の概念について理解する。
  • JavaScriptのプログラムの中で、多次元配列を作ることができるようになる。
  • JavaScriptのプログラムの中で、多次元配列を参照することができるようになる。また、要素の追加、結合、取得、削除ができるようになる。
  • 連想配列の概念について理解する。
  • JavaScriptにおける連想配列とオブジェクトの関係について理解する。
  • JavaScriptのプログラムの中で、連想配列を作ることができるようになる。
  • JavaScriptのプログラムの中で、連想配列を参照することができるようになる。また、要素の追加、結合、取得、削除ができるようになる。
  • 強いパスワードとはどういうものかを理解する。
  • TLSについて理解する。

配列

配列の生成

配列は、ひとつの変数を区切ってたくさんのデータ(配列の要素と呼ぶ)を保存できるようにしたものである。
データは順番を持つ箱に格納される。
データを保存したり取り出したりする時は、変数名[番号]という形で指定する。
配列では、添字に数字を使い、番号は0から始まる。
添字とはカギ括弧の中に書かれる値のことである。

配列
配列

配列の生成方法には、下記のようなものがある。
下記の例は全て同じ配列を生成している。

JavaScript
// パターン1
var array = ['hoge', 'fuga'];

// パターン2
var array = new Array('hoge', 'fuga');

// パターン3
var array = Array('hoge', 'fuga');

// パターン4
var array = [];
array[0] = 'hoge';
array[1] = 'fuga';

// array[0] が 'hoge'
// array[1] が 'fuga'

配列の操作

前にも述べたように、配列には、様々なメソッドが用意されている。
例えば、2つの配列を連結したい場合には次のようにする。
この例では、array1とarray2のそれぞれの配列を始めに生成し、その2つを4行目で結合して、arrayという変数に代入している。
結果としてarrayの中身は「[“佐藤”, “鈴木”, “田中”, “渡辺”, “伊藤”, “山本”]」となる。

JavaScript
var array1 = ["佐藤", "鈴木", "田中"];
var array2 = ["渡辺", "伊藤", "山本"];

var array = array1.concat(array2);

他にも下記の表のようないろいろなメソッドが用意されている。
ただし、基になる配列を変更してしまうもの(破壊的操作)と、concat()のように新しい配列を生成してそれを返すもの(非破壊的操作)があるので注意が必要である。

メソッド 説明
concat(ary) aryで指定した配列を現在の配列の後ろに連結した新しい配列を生成し、それを返す。
join(str) 配列の各値を 区切り文字列str でつなぐことによって得られる文字列を返す。
pop() 配列末尾の要素を値として返し、その後その要素を削除する。
push(val) valで指定した値を要素として配列の最後に加える。
reverse() 配列の要素の並び順を反転させる。
shift() 配列先頭の要素を値として返し、その後その要素を削除する。
slice(start[, end]) startからend-1番目の要素を抜き出す。
sort([func]) 要素を昇順に並び替える。funcで並び替えに使う関数を指定することもできる。
splice(start, cnt [, rep [, …]]) 配列内のstart〜start+cnt-1番目の要素をrepで置き換える。
toString() 要素を「,」で区切って並べた文字列を返す。
unshift(val) valで指定した値を要素として配列の最初に加える。

また、メソッドではないが、プロパティとして「length」がある。
lengthを使うことによって配列の要素の数を知ることができる。

プロパティ 説明
length 配列の中の要素の数

連想配列

配列の添字に意味のある文字列を使うと、ある文字列に関係する値をすぐに引き出すことができる。
例えば、学籍番号の入った配列を作ってその添字に名前を使うとすると、名前をもとに配列にアクセスすることにより、すぐに学籍番号を引き出すことができる。
このような配列のことを一般的に連想配列と呼ぶ。

JavaScriptには厳密には連想配列は存在しないが、Objectを使うことによって同様のことを実現できる。
下記の例では、objという変数に’taro’と’jiro’という2つの値が格納されており、それぞれにアクセスするための添字(ラベル)が’sato’と’suzuki’となっている。

JavaScript
// パターン1
var obj = { sato: 'taro', suzuki: 'jiro'};

// パターン2
var obj = { 'sato': 'taro', 'suzuki': 'jiro' };

// パターン3
var obj = {};
obj.sato = 'taro';
obj.suzuki = 'jiro';

// パターン4
var obj = {};
obj['sato'] = 'taro';
obj['suzuki'] = 'jiro';

// パターン5
var obj = new Object();
obj.sato = 'taro';
obj.suzuki = 'jiro';

// obj['sato'] が 'taro'
// obj['suzuki'] が 'jiro'

二次元配列

表計算のようなことをしようとする場合、これまで使ってきた配列だけでは機能が不足することがある。
例えば、次のようなデータがあるとしよう。

日付 始値 高値 安値 終値
2011年1月10日 82.690000 83.540000 82.379900 82.940000
2011年1月17日 82.800000 83.489900 81.819900 82.580000

これは、2011年の週毎のドル円の為替データである。
このデータを扱うためにはどのようにすれば良いでだろうか?
1つ考えられる方法としては、それぞれのカラムを配列として扱うことである。
例えば次のようになる。

var date =  ["2011年1月10日", "2011年1月17日", ...];
var start = [82.690000, 82.800000, ...];
var high =  [83.540000, 83.489900, ...];
var low =   [82.379900, 81.819900, ...];
var end =   [82.940000, 82.580000, ...];

確かにこれでもデータを扱うことはできるが、もう少し良い方法がある。
この様な時に使えるのが二次元配列である。
二次元配列とは表のように列と行によってデータを格納するための配列である。
例えば、次のように記述する。

var usdjpy = [
  ["2011年1月10日",82.690000,83.540000,82.379900,82.940000],
  ["2011年1月17日",82.800000,83.489900,81.819900,82.580000],
  ...
];

この例では、日付・始値・高値・安値・終値を1つの行として配列にし、更に週毎にその配列を作っている。
つまり「[“2011年1月10日”,82.69,83.54,82.3799,82.94]」もひとつの配列だし、それを集めた全体も配列である。
上の例ではusdjpyという変数には配列の配列、二次元配列が格納される。

さて、データを二次元配列に入れる方法は説明したが、これはどのようにして使えば良いのでだろうか?
使い方は二次元配列が配列の配列であることが解れば難しくない。
例えば、1行目の2列目を使うためには「usdjpy[0][1]」のように参照する。
配列は0番目から始まるため、1行目を表す添字は0になるし、2列目を表す添字は1となる。

var usdjpy = [
  ["2011年1月10日",82.690000,83.540000,82.379900,82.940000],
  ["2011年1月17日",82.800000,83.489900,81.819900,82.580000]
];
 
alert(usdjpy[0][1]);

実際に上のプログラムを実行すると、「82.69」という数字がアラートで表示されます。

セキュリティ

ネットワークを使うにあたって、セキュリティについて知っていることは非常に重要である。
本節では、配列の利用例もおりまぜながらセキュリティに関するスキルを身に着ける。

パスワードの強さと攻撃

皆さんに身近なセキュリティの話題の1つにパスワードがある。
パスワードはシステムにログインする場合など、様々な場面で使われる。
パスワードをつける際には、ある程度以上の長さにしなければいけない、大文字と小文字を混ぜるべき、数字や記号を入れるべき、辞書にある単語をそのまま使わない、などと言われることが多い。
これはなぜなのだろうか。
ここでは、実際の例などを示しながらその重要性を考えてみたい。

ブルートフォース攻撃

あるパスワードを破れ、と言われたらみなさんどういう方法を試すだろうか。
おそらく一番始めに思いつくのは総当りでは無いでだろうか。
これは力業だが、パスワードが短い場合は有効な手段である。
そのため、このような手段を、「力ずくで」、「強引に」という意味の「brute force」を使って、ブルートフォース攻撃という。

下のようなタイプの鍵を見たことは無いだろうか。
この鍵はそれぞれのリングに0〜9の数字が書かれており、3つの番号を合わせることによって鍵を開けることができる。

key

もし、3桁の0〜9までの数字のパスワードだということがわかっている場合、コンピュータがそのパスワードを解くのにどれくらいかかるだろう。
次のプログラムを見て欲しい。
このプログラムでは、3重ループのfor文の前後で時刻を計測し、その差、つまりかかった時間をalert()で表示している。
3重ループの部分では000〜999までの数字を表示させている。
0〜999を数え上げることも、コンピュータにとってはあっという間も無いような時間であることが確認できる。

HTML部分
<input type="button" value="3桁の0〜9までの数字、総当り" onclick="n3()">
<input type="text" id="text080201" value="000">
JavaScript部分
function n3() {
    var str = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
    var ele = document.getElementById("text080201");

    var t_start = (new Date).getTime();

    for (var i=0; i<str.length; i++) {
        for (var j=0; j<str.length; j++) {
            for (var k=0; k<str.length; k++) {
                ele.value = str[i] + str[j] + str[k];
            }
        }
    }

    var t_end = (new Date).getTime();

    alert("かかった時間は" + (t_end - t_start) + "ミリ秒です");
}
動作例



このように、0〜999まで数え上げるくらいのことはコンピュータにとっては非常に短時間に済んでしまう作業である。
このため、数字だけの短い文字列のパスワードは推奨されないのである。

では、小文字のアルファベットまで使えるようになるとどう変化するだろうか。

HTML部分
<input type="button" value="3桁の0〜9までの数字と英小文字、総当り" onclick="na3()">
<input type="text" id="text080202" value="000">
JavaScript部分
function na3() {
    var str = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
               "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
               "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
    var ele = document.getElementById("text080202");

    var t_start = (new Date).getTime();

    for (var i=0; i<str.length; i++) {
        for (var j=0; j<str.length; j++) {
            for (var k=0; k<str.length; k++) {
                ele.value = str[i] + str[j] + str[k];
            }
        }
    }

    var t_end = (new Date).getTime();

    alert("かかった時間は" + (t_end - t_start) + "ミリ秒です");
}
動作例



総当りにかかる時間が、だいぶ長くなったことが確認できただろう。

辞書攻撃

それでは、文字の種類を増やしたり、桁数を増やせば安心なのだろうか。
そうでもない。
一般的な単語をパスワードとして使ってしまうと、思いがけず素早くパスワードを当てられてしまうことがある。
辞書攻撃と言われる攻撃で、攻撃する側が辞書を持っていて、それを順に試してくるのである。

例えば、"university"という文字列があったとする。
10文字もあるので、ブルートフォース攻撃ではそこそこの時間がかかる。
しかし、辞書攻撃を用いれば、これもあっという間にパスワードを見つけることができる。
英語の辞書に載っている単語は、多くても数十万程度であろう。
少し多く見積もって100万語の辞書を使ってパスワードを使って試してみたとする。
これは実は、6桁(000000〜999999)のパスワードを試すことと同じで、コンピュータにとっては大した時間ではない。

これらの理由により、パスワードをつける際には、「ある程度以上の長さにしなければいけない、大文字と小文字を混ぜるべき、数字や記号を入れるべき、辞書にある単語をそのまま使わない」と言われるのである。

Webページのパスワード認証

Webページにアクセスをしていると、パスワードを求められることがある。
これは、Basic認証やDigest認証と呼ばれる機能を使って実現できる。
Basic認証もDigest認証もIDとパスワードのペアによってユーザを認証しているが、Basic認証の場合は暗号化されていないパスワードがネットワークを流れる。
このため、可能であればDigest認証を使うべきである。
以前は、Digest認証に対応していないブラウザもあったが、現在では非常に稀で、ほぼすべてのブラウザがDigest認証に対応している。

また、後に述べるTLSを用いることによって、通信路そのものを暗号化してしまうことも可能である。
この場合は、Basic認証でもパスワードは暗号化された通信路の中を流れることになる。

Digest認証の基本的な使い方は、あるディレクトリの下にアクセスするためにID/パスワードを求めるというものである。
例えば、public_html/info2/08 というディレクトリの下にアクセスする、
つまり https://web.sfc.keio.ac.jp/~[ログイン名]/info2/08/ にアクセスするときにID/パスワードを求めるようにするためには、
public_html/info2/08/.htaccessというファイルを作る必要がある。
public_html/info2/08/.htaccess には次のような内容を記載する。
最後に空行を入れることに注意して欲しい。

AuthUserFile	/home/[ログイン名]/.htdigest
AuthName	"Members Only"
AuthType	Digest
require 	valid-user
 

その後、Digestファイルを作成する。
Digestファイルは、ターミナルを立ち上げて、下記のようにして作成する。
ここで「$」から始まる行が実際に入力する行である。
ただし、「$」はプロンプトで入力する必要はない。

$ /usr/sbin/htdigest -c ~/../.htdigest "Members Only" [ユーザ名1]
Adding password for [ユーザ名1] in realm Members Only.
New password:
Re-type new password:
$ /usr/sbin/htdigest ~/../.htdigest "Members Only" [ユーザ名2]
Adding password for [ユーザ名2] in realm Members Only.
New password:
Re-type new password:

1番始めの行の「-c」は新しいファイルを作成することを指定している。
2人目以降のユーザを追加する際には「-c」は指定しない。
[ユーザ名1][ユーザ名2]のところには、ログインに使いたいユーザ名を指定する。
そうするとパスワードを聞かれるので、2回入力する。
これでDigestファイルが作成される。

より詳しくは http://www.sfc.itc.keio.ac.jp/ja/network_web_server.html を参照してほしい。

TLS

これまでは、作成したWebページにアクセスするためには、「http://...」といった感じのURLを使っていた。
これはプレーンなHTTPを使ってWebにアクセスすることを示している。
しかし、プレーンなHTTPでは、通信は暗号化されておらず、通信が傍受された場合には通信内容が覗き見られてしまう可能性がある。

このような問題を解決するためには、Transport Layer Security(TLS)を使う。
以前は、Secure Sockets Layer (SSL)と呼ばれる技術が使われていたが、現在は強固な暗号化に対応したより洗練されたTLSが開発され、WebにおいてもTLSが利用されている。
ただ、世の中では実際にはTLSが使われている場合でも、「SSL通信」のように呼ばれていることも多く、少々混乱しているので注意が必要である。

WebにTLSを使ってアクセスする場合は、「http://...」の代わりに「https://...」を使う。
最後の「s」がTLSを使っていることを示している。
「https://...」と指定することによって、WebサーバとWebブラウザの間で実際に使用するプロトコルのバージョンなどが調整され、暗号化された通信路が確立される。

httpとhttps

一般的にTLSの接続が確立されるときには、サーバ側からクライアント側に「サーバ証明書」と呼ばれるものが送られてくる。
サーバ証明書の確認には、公開鍵暗号系の暗号が使われる。
公開鍵暗号系の暗号の特徴は次のとおりである。
公開鍵暗号系では、公開鍵と呼ばれる広く公開してよい鍵と、秘密鍵と呼ばれる本人しか知らない鍵のペアが使われる。
その上で、秘密鍵で暗号化した文書は公開鍵で復号可能、公開鍵で暗号化した文書は秘密鍵のみで復号可能である。
このため、秘密鍵で暗号化された文書を見ると、間違いなく秘密鍵をもっている人がその暗号化された文章を作ったことが確認できる。
また逆に、公開鍵で暗号化された文書は秘密鍵を持っている人しか復号することができない。

先に述べた「サーバ証明書」、通信相手が確かに意図したサーバかを確認するために使うもので、認証局と呼ばれる機関が秘密鍵で署名(暗号化)をしている。
認証局の公開鍵は広く配られているので、その鍵を使って送られてきた「サーバ証明書」が正しいかどうかは誰でも確認(復号)できる。
ちなみに、認証局は階層構造で管理されており、その大元締めとなっている認証局の公開鍵は、ブラウザと一緒に配布されている。

GlobalオブジェクトとMathオブジェクト

Globalオブジェクト

システムで用意されている関数は、どこかのオブジェクトに属しています。Globalオブジェクトは、JavaScriptで最も基本的なオブジェクトです。以下にGlobalオブジェクトに属している関数の例を挙げます。

メンバ 意味
parseInt(str) 文字列strを整数に変換する。小数点以下は切り捨てる。
parseFloat(str) 文字列strを実数に変換する。
String(val) valを文字列に変換する。
Number(val) valを数字に変換する。

他にもたくさんの関数がありますので、自分でも調べてみてください。

Mathオブジェクト

三角関数や平方根など、数学に関わる演算機能を提供するのがMathオブジェクトです。例えば、Math.abs(数値)とすることによって、数値の絶対値を得ることができます。下に主要なMathオブジェクトの関数を挙げておきます。メンバがabs(num)の時には、先ほどのようにMath.abs(num)と記述します。

メンバ 意味
abs(num) numの絶対値を求める。
ceil(num) numの小数点以下を切り上げる。
floor(num) numの小数点以下を切り捨てる。
round(num) numの小数点以下を四捨五入する。
max(num1, num2) num1、num2のうち大きい数を求める。
min(num1, num2) num1、num2のうち小さい数を求める。
pow(num1, num2) num1のnum2乗を求める。
sqrt(num) numの平方根を求める。
exp(num) 指数関数。eのnum乗を求める。
log(num) numの自然対数を求める。
sin(num) サインを求める。numはラジアン。
cos(num) コサインを求める。numはラジアン。
tan(num) タンジェントを求める。numはラジアン。
random( ) 0〜1未満の乱数を返す。

上記の中でrandom()だけは、引数をとらないちょっと風変わりなものになっています。random()は、何も無いところから0〜1未満の乱数を生成します。乱数というのは毎回変わる適当な値です。例えば、「n = random()」のようにすると、nには0〜1未満の値(0.1や0.2345)が入ります。

また、Mathオブジェクトには定数も設定されています。これは関数ではありませんが、以下に挙げておきます。例えば、円周率πを使いたい場合には、プログラムの中で「3.1415...」と書く代わりに「Math.PI」と書くことができます。

メンバ 意味
PI 円周率π。
E 自然対数の底。あるいはネイピア数e。

練習問題8-

配列を使った簡単なおみくじプログラムを作成しなさい。
ただし、JavaScriptのスケルトンは次のとおりである。

function mikuji(){
  var unsei = new Array("大吉","中吉","小吉","吉","末吉","凶","大凶");
  var uranau = /* ここを書く */;

  document.getElementById("res").innerHTML = /* ここを書く */;
}

練習問題8-

上の例で出てきた、数字3桁のブルートフォース攻撃をためし、かかった時間をアラートで表示するプログラムを作成しなさい。

練習問題8-

小文字のみ使った英数字3桁のブルートフォース攻撃をためし、かかった時間をアラートで表示するプログラムを作成しなさい。

練習問題8-

大文字小文字の両方を使った英数字3桁のブルートフォース攻撃をためし、かかった時間をテキストエリアに表示するプログラムを作成しなさい。

練習問題8-

数字6桁のブルートフォース攻撃をためし、かかった時間をテキストエリアに表示するプログラムを作成しなさい。
これは、100万単語から成る辞書を使った辞書攻撃と同じ時間である。

練習問題8-

認証局は証明書を発行する機関であり、多くの場合一般企業である。
また、証明書は電子ファイルであるため、生成するのに費用はほとんどかからない。
これはボロ儲けのチャンスである。
しかし実際にはそうはなっていない。
なぜ認証局を立ち上げるのが難しいか考え、その考えを示したWebページを作成しなさい。

またそのページに、ID: info2, Password: Keio#University でアクセスできるようにDigest認証をかけなさい。

canvasと多重繰り返し

目標

ここでは多重繰り返しを身につける。
多重繰り返しは単なる単独の繰り返しの入れ子構造であり、繰り返しの基本がわかっていれば新しく学ぶことは特にない。

また、HTMLのcanvas要素に対してJavaScriptで描画する方法を学習する。

  • while文の二重繰り返しの挙動を理解できる。また、while文の二重繰り返しを書くことができる。
  • for文の二重繰り返しの挙動を理解できる。また、for文の二重繰り返しを書くことができる。
  • for文の二重繰り返しにおいて、変数の変化を正しく追うことができる。
  • 三重以上の繰り返しを正しく使うことができる。
  • canvas要素に円や矩形などの基本的な図形の描画ができる。
  • canvas要素に複雑な図形の描画ができる。

canvasと描画

多重繰り返しについて説明する前に、HTMLの要素の1つであるcanvas要素について説明する。

canvas要素

canvas要素は、Webページにプログラムによる描画領域を確保するための要素である。
次のように記述する。
この記述では200×200の描画領域を確保している。
タグで囲まれた「四角形を描画する領域」は、もしもcanvas要素をサポートしていないブラウザでこのページが表示された場合に代替として表示される文字列である。
最新のFirefoxやSafariなどのブラウザを利用している限りは、このような文字列が表示されることはない。

HTML
<canvas id="canvas" width="200" height="200">四角形を描画する領域</canvas>

キャンバス要素をHTML文書の中に挿入するだけでは、単にページに空間が空くだけである。
この文章の直後に空間が空いているが、これは上記の記述をこのページに挿入しているためである。
実際にcanvas要素を活用するためには、JavaScriptによって描画をすることが必要である。
次節以降ではJavaScriptによる描画方法について説明する。

四角形を描画する領域

JavaScriptによる描画の基本

canvas要素で確保した描画空間にJavaScriptを使って描画をするためには、canvas要素をプログラムの中で取得し、そこから更に描画コンテクストを取得する必要がある。

HTML
<canvas id="canvas" width="200" height="200">四角形を描画する領域</canvas>
JavaScript
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.strokeRect(50, 50, 100, 100);

上記はcanvas要素を使った四角を描画するプログラムである。
JavaScriptの1行目でcanvas要素を取得している。
canvas要素を取得することによって、プログラムでcanvas要素に対して描画などの処理ができるようになる。
2行目では、二次元描画用のコンテクストを取得している。
コンテクストというのは解りにくいかもしれないが、描画を行うにあたり、どのような座標を使うのか、四角や円などどのような図形を指定することが出来るのかなどを定義したものである。
つまり、ここでは「’2d’」と指定することによって、二次元描画コンテクストを取得している。
二次元があるということは「’3d’」と書くと三次元描画もできるのかと思うが、残念ながら現在のところ唯一使える描画コンテクストは「’2d’」のみである。
将来的には三次元描画コンテクストも使えるようになるかも知れない。

キャンバスの描画コンテクストを取得すると、そこに存在している幾つかのプロパティを変更することができる。
例えば、線の色や太さなどである。
JavaScriptで線の太さを変更するためには、描画コンテクストctxを取得した後に(変数名は「ctx」でなくとも問題ないが、ここでは便宜上、上記の続きでとみなして「ctx」を使う)、
lineWidthプロパティを変更する。
また、線の色を変更するためにはstrokeStyleプロパティを変更する。
更に、塗りつぶしを行う場合の色は、fillStyleプロパティを変更することによって指定が可能である。

次のプログラムを見てほしい。
JavaScriptの4行目から6行目までで線の太さ、色、塗りつぶしの色を指定している。
また、8行目と9行目でそれぞれ、塗りつぶした四角を描画し、四角の枠を描いている。

このプログラムのHTML部を見ると、普段はヘッダに入っているscript要素がbodyに入っている。
これはcanvas要素を作った後に、プログラムを読み込むようにするためである。
通常はこのような操作はせず、onloadイベントを使うが、今回はこのようにしてプログラムを実行してみてほしい。

HTML *
<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8">
    <title>描画の例</title>
  </head>

  <body>
    <h1>描画の練習</h1>
    <canvas id="canvas" width="200" height="200">四角形を描画する領域</canvas>
    <script src="draw.js"></script>
  </body>

</html>
JavaScript(draw.js)
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

ctx.lineWidth = 10.0;
ctx.strokeStyle = 'black';
ctx.fillStyle = 'lightgrey';

ctx.fillRect(50, 50, 100, 100);
ctx.strokeRect(50, 50, 100, 100);

JavaScriptによる描画の基本(パス)

また、描画においては、より複雑な図形を描画するためにパスという概念がある。
これは、いろいろな描画メソッドを組み合わせて図形を描く時に使われるものである。
例えば、正六角形を描画するメソッドは二次元描画コンテクストには存在しないが、次のようにすることによって正六角形を描くことができる。
ここで、beginPath()メソッドからclosePath()メソッドまでがパスを定義している部分となる。
その中でmoveTo()メソッド(ペン先を上げた状態で座標に動かす)や、lineTo()メソッド(ペン先を下ろした状態で指定した座標に動かす。つまり、現在ペン先がある所から指定した座標まで直線を引く。)を使って正六角形を描き、その上でfill()メソッドによって塗りつぶし、また、stroke()メソッドによって直線を引いた部分に色をつけている。
fill()メソッドやstroke()メソッドによって色をつけるまでは、実際には目に見える形にはならないことに気をつけてほしい。

HTML
<canvas id="canvas" width="200" height="200">正六角形を描画する領域</canvas>
JavaScript
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var x = 100;  // 中心点のX座標
var y = 100;  // 中心点のY座標
var r = 80;   // 半径

ctx.lineWidth = 3.0;
ctx.strokeStyle = 'black';
ctx.fillStyle = 'lightgrey';

ctx.beginPath();
ctx.moveTo(x + Math.sin(0 * 2 * Math.PI / 6) * r, y - Math.cos(0 * 2 * Math.PI / 6) * r);
ctx.lineTo(x + Math.sin(1 * 2 * Math.PI / 6) * r, y - Math.cos(1 * 2 * Math.PI / 6) * r);
ctx.lineTo(x + Math.sin(2 * 2 * Math.PI / 6) * r, y - Math.cos(2 * 2 * Math.PI / 6) * r);
ctx.lineTo(x + Math.sin(3 * 2 * Math.PI / 6) * r, y - Math.cos(3 * 2 * Math.PI / 6) * r);
ctx.lineTo(x + Math.sin(4 * 2 * Math.PI / 6) * r, y - Math.cos(4 * 2 * Math.PI / 6) * r);
ctx.lineTo(x + Math.sin(5 * 2 * Math.PI / 6) * r, y - Math.cos(5 * 2 * Math.PI / 6) * r);
ctx.lineTo(x + Math.sin(6 * 2 * Math.PI / 6) * r, y - Math.cos(6 * 2 * Math.PI / 6) * r);
ctx.closePath();
ctx.fill();
ctx.stroke();

また、ここで気をつけるべきことがもう一つある。
通常のグラフでは、X軸は左から右、Y軸は下から上に向かって数字が増えていくが、canvas要素で描画をする場合にはY軸は上から下に数字が大きくなる。
座標を計算する場合はこの点に注意してほしい。

> canvasの座標系

描画のためのメソッド

それでは、実際の描画方法についてみていこう。
以下に描画に使われる代表的なメソッドをまとめる。

メソッド 説明
fillRect(x, y, w, h) (x, y)で指定された座標を起点として、幅w、高さhの塗りつぶされた枠の無い四角形を描画する。lineTo()などと異なり、stroke()メソッドやfill()メソッドを用いなくとも実際に四角形が描画される。
strokeRect(x, y, w, h) (x, y)で指定された座標を起点として、幅w、高さhの塗りつぶされていない枠のみの四角形を描画する。lineTo()などと異なり、stroke()メソッドやfill()メソッドを用いなくとも実際に四角形が描画される。
clearRect(x, y, w, h) (x, y)で指定された座標を起点として、幅w、高さhの範囲の図形を消去する。
moveTo(x, y) ペン先を上げた状態で、(x, y)で指定された座標にペン先を動かす。
lineTo(x, y) 現在ペン先がある位置から、(x, y)で指定された座標まで直線を引く。
rect(x, y, w, h) (x, y)で指定された座標を起点として、幅w、高さhの四角形を描画する。
arc(x, y, r, sAng, eAng, anticlockwise) (x, y)を中心とするsAngで指定された角度からeAngで指定された角度までの半径rの弧を描く。また、anticlockwiseがtrueの場合は反時計回り、falseの場合は時計回りとなる。
bezierCurveTo(x0, y0, x1, y1, x2, y2) 3次ベジェ曲線を描く。現在の座標を始点、(x2, y2)を終点、(x0, y0)を始点に対する制御点、(x1, y1)を終点に対する制御点とするベジェ曲線を描く。
fillText(text, x, y) textで指定された文字列を座標(x,y)に書く。「ctx.font=”20pt 明朝”;」のように描画コンテクストのfontプロパティを変更することによって、フォントを変更することが出来る。

キャンバス全体を消去したい場合は、clearRect()を使って「ctx.clearRect(0, 0, canvas.width, canvas.height);」の様にすると良い。
ここでctxは描画コンテキストである。
また、canvasはキャンバス要素が入った変数である。
canvas.widthとcanvas.heightはそれぞれ、キャンバスの幅およびキャンバスの高さが自動的に設定される。

多重繰り返し

二重ループ

繰り返しについては、while文やfor文などが存在することは既に説明した。
しかし、whileループやforループを単独で使うだけでは、機能として不足することもある。
先ほどのcanvas要素を使って、次のようなチェッカーフラグの様な模様を描くことを考えてみよう。

四角形を描画する領域

このような模様を描くためには、もちろん根気づよく次のようにプログラミングする方法もある。

HTML
<canvas id="canvas" width="200" height="200">四角形を描画する領域</canvas>
JavaScript
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

ctx.fillRect(  0,   0, 20, 20);
ctx.fillRect( 40,   0, 20, 20);
ctx.fillRect( 80,   0, 20, 20);
ctx.fillRect(120,   0, 20, 20);
ctx.fillRect(160,   0, 20, 20);
 
ctx.fillRect( 20,  20, 20, 20);
ctx.fillRect( 60,  20, 20, 20);
ctx.fillRect(100,  20, 20, 20);
ctx.fillRect(140,  20, 20, 20);
ctx.fillRect(180,  20, 20, 20);
 
ctx.fillRect(  0,  40, 20, 20);
ctx.fillRect( 40,  40, 20, 20);
ctx.fillRect( 80,  40, 20, 20);
ctx.fillRect(120,  40, 20, 20);
ctx.fillRect(160,  40, 20, 20);

...

しかし、これでは人間が頑張って、コンピュータに楽をさせているようなものである。
もう少し人間が楽になる方法は無いだろうか?
繰り返しを使えばもう少し楽ができるだろう。
次のプログラムを見てほしい。

HTML
<canvas id="canvas" width="200" height="200">四角形を描画する領域</canvas>
JavaScript
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var y;
for (y=0; y<200; y = y + 20) {
  if (y % 40 == 0) {
    ctx.fillRect(  0, y, 20, 20);
    ctx.fillRect( 40, y, 20, 20);
    ctx.fillRect( 80, y, 20, 20);
    ctx.fillRect(120, y, 20, 20);
    ctx.fillRect(160, y, 20, 20);
  } else {
    ctx.fillRect( 20, y, 20, 20);
    ctx.fillRect( 60, y, 20, 20);
    ctx.fillRect(100, y, 20, 20);
    ctx.fillRect(140, y, 20, 20);
    ctx.fillRect(180, y, 20, 20);
  }
}

しかし、これでも同じことを何度も書かなければならない。
そこで登場するのが二重ループである。
ループの中にもう一つループを追加することによってもう少し簡単に書くことができる。

HTML
<canvas id="canvas" width="200" height="200">四角形を描画する領域</canvas>
JavaScript
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var x, y;
for (y=0; y<200; y+=20) {
  for (x=0; x<200; x+=20) {
    if ((x+y)%40 == 0) {
      ctx.fillRect(x, y, 20, 20);
    }
  }
}

この例では、変数yによって制御されるループの中に、変数xによって制御されるループが入っている。
これが二重ループである。
次に二重ループのフローチャートを示す。
一見複雑そうだが、流れを一つ一つ確認していけば理解できるはずである。

二重ループのフローチャート

練習問題7-

  1. *印のついたHTMLとdraw.jsを作成し、プログラムを実行してみなさい。
  2. ctx.fillRect()の行とctx.strokeRect()の行を入れ替えたプログラムを作成し、何が起きるかを確認しなさい。

練習問題7-

下記のような、nを入力して正n角形を描画するようなプログラムを作成しなさい。


正n角形を描画する領域

練習問題7-

上のプログラムを使って、辺の長さからπを求めるプログラムを作成しなさい。

π = ???

正n角形を描画する領域

練習問題7-

下記のような星印を描きなさい。

四角形を描画する領域

練習問題7-

次のような図形を描画しなさい。

四角形を描画する領域

練習問題7-

次のような図形を描画しなさい。

四角形を描画する領域

練習問題7-

次のような図形を描画しなさい。

四角形を描画する領域

練習問題7-

下記のように、点を表示しながらモンテカルロ法によってπを求めるプログラムを作成しなさい。
また、ボタンを押すたびに精度が上がっていくようにしなさい。
モンテカルロ法でπを計算するためには、正方形に内接する円を考え、適当な点を選んだ上で、その点が円の中に入るかどうかを確かめる。
その上で、円に入る点の割合からπを算出する。

参考:練習問題4-3

π = ???

モンテカルロ法によるπの計算

オブジェクトと一次元配列、HTMLとJavaScript

目標

ここでは、簡単なオブジェクトおよび一次元配列、JavaScriptからHTMLの要素を扱う方法について学ぶ。

  • 一次元配列の概念について理解する。また、一次元配列の参照ができるようになる。
  • getElementsByTagName()が使えるようになる。
  • getElementById()が使えるようになる。
  • getElementsByClassName()が使えるようになる。
  • JavaScriptによるDOMの操作ができるようになる。
  • getElementById()やgetElementsByClassName()等が返す値の構造を理解する。

オブジェクト

オブジェクトは値の集合である。
例えば、名前というオブジェクトは、日本の場合は「姓」と「名」で出来ている。
また、位置というオブジェクトは「緯度」と「経度」で出来ているかもしれない。
更には、人を表すオブジェクトは、先に出てきた「名前」というオブジェクト、つまり「姓」と「名」を含むオブジェクトと「年齢」「性別」と表現することができる。

名前の構造
位置の構造
人の構造

オブジェクトリテラル

JavaScriptにおいて、実際の値を使ってオブジェクトを表現するためにはオブジェクトリテラルが用いられる。
オブジェクトリテラルは次のような書式を持つ。

{プロパティ名: 値, プロパティ名: 値, ...}

プロパティ名というのは、オブジェクトの中に存在する個々の値につけられた名前である。
例えば先ほどの名前をオブジェクトリテラルで書くと次のように書く事ができる。
ここで「”慶應”」「”太郎”」のように値がダブルクォートで囲まれているのは値が文字列だからである。

{familyName: "慶應", firstName: "太郎"}

プロパティ名は空白を含む任意の文字列を利用する事ができる。
空白を含む場合にはプロパティ名をクォートやダブルクォートで囲む必要がある。
しかし、後に述べるオブジェクトの参照、つまり値の使い方の際に制限がでるので、空白や「-」などの利用は避けておいた方が無難である。
漢字やひらがなを使う事も出来るが、止めておいた方がよいだろう。

{"family name": "慶應", "first-name": "太郎"}

また、人のようにオブジェクトを内包したオブジェクトの場合は下記のように記述することが可能である。
ここでは、「name」というプロパティは「{familyName: "慶應", firstName: "太郎"}」というオブジェクトにひもづけられているので注意が必要である。

{name: {familyName: "慶應", firstName: "太郎"}, age: 19, gender: "male"}

オブジェクトの生成

オブジェクトが入った変数を作るのは簡単である。
予め初期化されたオブジェクトを作るためには下記のように記述する。

var 変数名 = {プロパティ名: 値, プロパティ名: 値, ...};

例えば、人のオブジェクトを生成するためには下記のようにすれば良い。
読みやすいように改行してあるが、改行はあっても無くても問題ない。
見やすいように書くよう心がけるとよい。

var human = {
  name: {familyName: "慶應", firstName: "太郎"},
  age: 19,
  gender: "male"
};

JavaScriptでは、他にもnew演算子を用いてオブジェクトを生成する方法がある。
new演算子を用いてオブジェクトを生成するためには、コンストラクタを用いる。
ここではあまり詳しいことは述べないが、Date()などがこの例である。
Date()を使ったプログラムでは、下記のようにオブジェクトを生成する。

var date = new Date();

これは、システムが提供しているオブジェクトであるDateオブジェクトを使って、Dateオブジェクトが持つ様々な機能が使える新たなオブジェクトを作り出し、それを変数dateに代入している。
Dateオブジェクトには、予めそのメンバとして、toLocaleString()のような関数(オブジェクトにひもづけられている関数をメソッドと呼ぶ)が定義されており、変数dateを通じてこれらを利用することが出来る。
つまり、オブジェクトには、本来、関数も格納することができますが、これについては追々みていくこととする。

オブジェクトの参照

オブジェクトを変数に入れたら、当然それを使う事を考えなければならない。
プログラムの中でオブジェクトの中の値を参照するためには次のように表現する。

変数名.プロパティ名
変数名["プロパティ名"]
変数名['プロパティ名']

どの行も同じ値を表しているが、1行目の表現方法の場合、注意が必要である。
プロパティ名が「123」という数字だったり、「first-name」の様にマイナスを含んでいたりして、変数名の命名規則に則っていない場合は問題がおきるからである。
これが、上で空白やマイナスなどの文字列は使わない方が無難だと言った理由である。

また、上のhumanの例では、nameの中にfamilyNameなどがはいっている。
このような場合は次のように書く。

変数名.プロパティ名1.プロパティ名2
変数名["プロパティ名1"]["プロパティ名2"]
変数名['プロパティ名1']["プロパティ名2"]

具体的に「”慶應”」という値が入っている部分は次のようになる。

human.name.firstName
変数名["name"]["firstName"]
変数名['name']["firstName"]

さて、では実際のプログラムの中ではどのように利用するのであろうか。
下記をみて欲しい。
下記は、「human」というオブジェクトを生成し、そのオブジェクトが含むそれぞれのプロパティの値を表示させた例である。
例では、いろいろな表現があることを示す為に、「human.name.familyName」「human.name[“firstName”]」など異なった表現を使っているが、不必要に表現を混ぜないことがプログラムの見やすさを向上させることに注意が必要である。

/*
 *  オブジェクトの生成
 */
var human = {
  name: {familyName: "慶應", firstName: "太郎"},
  age: 19,
  gender: "male"
};

/*
 *  プロパティの表示
 */
alert("姓: " + human.name.familyName);
alert("名: " + human.name["firstName"]);
alert("年齢: " + human.age);
alert("性別: " + human['gender']);

一次元配列

多くのプログラミング言語では、多数のデータを扱うために配列という仕組みを持っている。
JavaScriptも例外ではない。
配列とは、変数名は1つのまま、それに番号をつけて複数の値を記憶できるようにしたものである。

配列

配列の中の1つ1つの値を記憶できる場所のことを「要素」と呼ぶ。
上でも書いたが、配列の場合、変数名は配列全体に対して1つだけである。
配列全体は沢山の要素の集まりである。
それぞれの要素が、今まで学習してきた変数のように使える。
逆に言うと、変数名だけでは、これまでの変数のようには扱うことができないので注意が必要である。

配列リテラル

配列についてもリテラルが決まっている。
配列リテラルは次のとおりである。

[値, 値, 値, ...]

値の数は任意で、0個以上の必要な数だけ指定することができる。
0個の場合には空の配列が生成される。

実際には次のような記述となる。

["佐藤", "鈴木", "田中", ...]

上の例では全ての要素の値が文字列になっているが、JavaScriptでは、要素毎に値の型を変える事ができる。
例えば、「["a", 3]」と書くと、1つめの要素の値は文字列だが、2つめの要素の値は数値として扱われる。
更には、オブジェクトの配列を作ったり、配列をオブジェクトのプロパティの1つに指定したりすることも可能である。

配列の生成

配列を生成する場合にもオブジェクトと同様に、配列リテラルで初期化された配列を生成する方法と、コンストラクタを使う方法がある。
ここでは、配列リテラルを使った方法についてみていく。
配列リテラルを使った方法は簡単で、下記のようになる。

var 変数名 = [値, 値, 値, ...];

実際にプログラムの中で使うと下記のようになる。
この例では、familyNameという変数に「”佐藤”」「”鈴木”」「”田中”」の3つの文字列が入った配列を代入している。

var familyName = ["佐藤", "鈴木", "田中"];

また、空の配列(要素が1つもない配列)を作るためには次のようにする。

var familyName = [];

配列の操作

配列オブジェクトには、様々なメソッドが用意されている。
ここではその幾つかを紹介する。

要素の追加

先頭に要素を追加(unshift)
var array = ['b', 'c'];

array.unshift('a');
alert(array); // ['a', 'b', 'c']
末尾に要素を追加(push)
var array = ['a', 'b'];

array.push('c');
alert(array); // ['a', 'b', 'c']

要素の結合

2つの配列を連結した配列を生成(concat)
var array1 = ['a', 'b'];
var array2 = ['c', 'd'];

// 新しい配列
var array = array1.concat(array2);

alert(array);  // ['a', 'b', 'c', 'd']
alert(array1); // ['a', 'b']
alert(array2); // ['c', 'd']

要素の取得

配列の要素数を取得(length)
var array = ['a', 'b', 'c'];
var len = array.length;

alert(len); // 3
何番目の要素に指定した値があるかを取得(同じものが複数存在する場合、最初の要素)(indexOf)
var array = ['a', 'b', 'c'];
var index = array.indexOf('b');

alert(index); // 1
何番目の要素に指定した値があるかを取得(同じものが複数存在する場合、最後の要素)(lastindexOf)
var array = ['a', 'b', 'c'];
var index = array.lastIndexOf('c');

alert(index); // 2

要素の削除

先頭を削除(shift)
var array = ['a', 'b', 'c'];

array.shift();
alert(array); // ['b', 'c']
末尾を削除する(pop)
var array = ['a', 'b', 'c'];

array.pop();
alert(array); // ['a', 'b']

要素内容を辞書順にソート

var array = ["e", "c", "b", "a", "d"];

array.sort();
alert(array); // ["a", "b", "c", "d", "e"]

配列の参照

配列の参照は、オブジェクトの参照と似ている。
変数名の後に角括弧をつけ、その中に番号を入れて指定する。
例えば、array という名前の配列の中の2番目の要素を参照するためには下記のように表記する。

array[1];

ここで気をつけなければならないことは、配列の番号が0番から始まることである。
2番目の場合は、0, 1なので「1」を指定する。
また、数字の代わりに変数を指定することもできる。
下に例を示します。この例では1行目でarrayという配列を作り、3行目で変数nに1を代入している。
4行目では、変数nを使って0から数えてn番目の要素を表示している。

var array = ["佐藤", "鈴木", "田中", "渡辺", "伊藤", "山本"];

var n = 1;
alert(array[n]);

また、for文と組み合わせることによって、全ての要素を順に出力することも可能である。
下の例では、lengthプロパティを使ってfor文で繰り返しを作り、全ての配列要素に対して「○番目: ××」のように表示をしている。

var array = ["佐藤", "鈴木", "田中", "渡辺", "伊藤", "山本"];

var i;
for (i = 0; i < array.length; i++) {
  alert(i + "番目: " + array[i]);
}

オブジェクトと配列

実は、オブジェクトと配列には、その表現方法をみてもわかるように類似性がある。
プロパティが数字のオブジェクトを配列とみることもできる。
ただし、「obj.0」「obj.1」や「obj[0]」「obj[1]」などの表現はできないので注意が必要である。
この場合は、「obj[“0”]」「obj[“1”]」のように表現する必要がある。
プロパティは、オブジェクトでは文字列だが、配列では数字なのである。

HTMLとJavaScriptの結びつけ

要素と名前付け

HTMLでは各要素にIDやクラスをつけることができる。
IDやクラスをつけることによって、その要素だけに対してCSSでスタイルを指定することができた。
JavaScriptにおいても、IDやクラスをつけておくことによって、その要素を指定しやすくなる。

id

id属性は、要素を識別するために固有のID(識別子)を付与するものである。
1つの文書(ページ)内で同じのIDを複数つけることはできない(つまり、一意でなければならない)。

id属性を指定する目的は、CSSで装飾する要素を指定したり、JavaScriptで特定要素を参照して処理を行うためである。

また、a要素にページ内の指定箇所を参照できる終点(id=”ID”)にも使われ、開始タグには <a href="#ID名"> の形式で IDにハッシュ(#)を記述する。
このIDは、div要素や見出し要素内などに記述したものを指定することができる。

class

class属性は、その要素にクラス名を指定する。
class属性はid属性と異なり、ひとつの文書内に同じクラス名を何度でも用いることができる。
また、半角スペースで区切って、1つの要素に複数のクラスを適用することもできる。

JavaScriptによる要素の取扱

JavaScriptからHTML要素を参照する場合は、まずその要素をJavaScriptのプログラムの中に取り込む必要がある。
ここでは、IDやクラスを使ったHTML要素とJavaScriptの結びつけについて説明する。

getElementById()

JavaScriptからIDを指定してHTML要素を紐付ける関数として、documentオブジェクトにgetElementById()メソッドが用意されている。
getElementById()メソッドはIDを引数にとり、そのIDを持つHTML要素を返す。
返り値を変数に代入したりすることによって、以後JavaScriptからその要素に対して簡単にアクセスができるようになる。

HTML
...
<p id="p1234">テスト1</p>
<p>テスト2</p>
<button onclick="showContent();">Click Me</button>
...
JavaScript
function showContent() {
  var ele = document.getElementById("p1234");
  alert(ele.innerHTML);
}

テスト1

テスト2

HTMLのDOM

上記のJavaScriptでは、ID属性がp1234という値の要素を、新しい変数eleに代入している。
その後アラートで、ID属性がp1234という値の要素のHTML、つまり指定されたID属性のある開始タグとその終了タグの間に書かれたHTML全て(=テスト1)が出力されている。

getElementsByClassName(“CLASS名”)

getElementsByClassName()は、指定したclass属性を持つ要素を全て取得する。
下の例では、「aaa」というclass属性を持つ要素を取得している。
ここで、「aaa」というclass属性を持つ要素は複数ある可能性があるため(事実、下の例では複数の要素が「aaa「というclass属性を持っている)、返り値を格納している変数classesは配列となっている。

HTML
<p class="aaa">要素1</p>
<p class="aaa bbb">要素2</p>
<p class="ccc aaa bbb">要素3</p>
<p class="aaa ccc bbb">要素4</p>
<p class="aaa bbb">要素5</p>
<button onclick="numOfaaa();">Click Me</button>
JavaScript
function numOfaaa() {
  var classes = document.getElementsByClassName("aaa");
  alert(classes.length);
}

要素1

要素2

要素3

要素4

要素5

1つのタグの中に、class属性を複数指定できるように、JavaScriptでも複数のclass名を同時に指定することもできる。
複数指定する場合は以下のようにスペースで区切って指定する。

HTML
<p class="aaaa">要素1</p>
<p class="aaaa bbbb">要素2</p>
<p class="cccc aaaa bbbb">要素3</p>
<p class="aaaa cccc bbbb">要素4</p>
<p class="aaaa bbbb">要素5</p>
<button onclick="numOfaaaacccc();">Click Me</button>
JavaScript
function numOfaaaacccc() {
  var classes = document.getElementsByClassName("aaaa cccc");
  alert(classes.length);
}

要素1

要素2

要素3

要素4

要素5

getElementsByTagName(“タグ名”)

getElementsByTagName()は、タグ名を指定してHTML要素を取得するためのメソッドである。
getElementsByTagName()も、getElementsByClassName() と同様に、指定したタグ名を持つ要素を全て取得し、配列を返す。
getElementsByTagName()では、id属性やclass属性が付加されていても関係なく、指定したタグ名のものなら全て取得される。

HTML
<p>要素1</p>
<p>要素2</p>
<p>要素3</p>
<p>要素4</p>
<p>要素5</p>
JavaScript
var pAll = document.getElementsByTagName("p");
alert(pAll.length);

DOM

HTMLの文書は構造化された文書の代表のようなものである。
ただ、これまではあまりそのことを意識した使い方はしなかったかもしれない。
しかし、プログラムからHTMLの文書を操作するには、その構造を意識する必要がある。
HTML文書のある部分の色を変えたり、他のテキストと置換するようなことを考えた場合、「HTML文書のある場所」を指定する必要があるからである。
ここでは、HTML文書構造を意識して、プログラムからアクセスするための手法について学ぶ。

HTML文書と木構造

HTML文書は実は木構造で表現することができる。
次のHTML文書を見てほしい。
非常に初歩的なHTML文書だが、この文書も構造を持っている。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>JavaScript</title>
  </head>
  <body>
    <h1>JavaScriptとは</h1>
    <p>JavaScriptは、プログラミング言語の1つで、ブラウザ上で動作するという特徴を持つ。</p>
  </body>
</html>

この文書の構造は、html要素の中にhead要素とbody要素があり、head要素の中にはメタ要素とタイトル要素がある。
これらの関係は下記のような木構造として表現することができる。

HTMLの木構造

DOM

HTML文書は上記の様に木構造を成している。
では、「HTML文書のある場所」をどのようにして示すのであろうか。
この問題を解決するためにDOMを使う。
DOMとは、Document Object Modelの略で、文書をオブジェクトとして扱うための取り決めである。
難しそうだが、基本的には上で述べた木構造と等価なものである。
具体的に見ていこう。

下記の図を見てほしい。
この図は、上の木構造の図に”document”というノードと若干の説明が加わった図となっている。

HTMLのDOMの説明

上で、document.getElementById()という関数を紹介した。
実は、これが正にDOMモデルのインターフェイスそのものである。
この関数の意味は、documentという文書(全てのHTML文書の一番上のレベルのオブジェクトはJavaScriptではdocumentになる)の中から指定したIDをもつ要素をもってくる、というものである。
つまり、上の木構造を全探索し、指定したIDをもつノードを返り値とする。

DOMのインターフェイスは他にもある。
要素を格納しているオブジェクトは様々なプロパティ(値)を持っている。
例えば、ある要素に対してfirstChildというプロパティを指定すると、1つ目の子供要素を得ることができるし、childNodes[1]というプロパティを指定すると2つめの子供要素を得ることができる。
ここで鉤括弧の中が1なのは、JavaScriptの場合、配列は0から始まるためである。
例えば、タイトルの「JavaScript」という文字が入っている要素は次のようにして指定することができる。

document.childNodes[1].firstChild.childNodes[1];

ただし、HTMLファイルに改行やタグとタグの間に空白があったりすると、その改行や空白が要素として認識されてしまうことがあるため、注意が必要である。
次のように改行等を含めずに書く必要があるかもしれない。

<!DOCTYPE html><html id='toplevel'><head><meta charset="utf-8"><title>JavaScript</title></head><body><h1>JavaScriptとは</h1><p>JavaScriptは、プログラミン>グ言語の1つで、ブラウザ上で動作するという特徴を持つ。</p></body></html>

また、要素を格納したオブジェクトには、firstChildやchildNodes以外にも様々なプロパティが存在する。
例えば、innerHTMLというプロパティでは、その要素が内包する木構造のHTMLが得られる。
プロパティの例を下に示す。

プロパティ 説明
attributes[] ノードの属性の配列。
childNodes[] 子要素の配列。
firstChild 最初の子要素
innerHTML ノード内のHTML。
innerText ノード内のテキスト。
lastChild 最後の子要素。
parentNode 親要素。
style ノードのスタイルを指定する属性。
value ノードのvalueプロパティの値。

練習問題5-

prompt()を使って6つの名前を入力してもらって配列に入れ、その中から3つずつ2回に分けてalert()で表示するプログラムを作成せよ。


練習問題5-

prompt()を使って5つの文字列を入力してもらい、辞書順に1つずつalert()で表示するプログラムを作成せよ。

ヒント: sort()メソッドを使うことができる。


練習問題5-

p要素が複数含まれているページを作り、getElementsByTagName()を使ってp要素の数を数え、その数をalert()で表示するプログラムを作成しなさい。


練習問題5-

p要素が複数含まれているページを作り、getElementsByTagName()を使ってp要素の数を数え、その数をテキストエリアに表示するプログラムを作成しなさい。



このページのp要素の数は、つです。

練習問題5-

次のようなHTMLがあるとき、cccを含んだ要素、aaaとbbbを含んだ要素の内容を変更するボタンを作成しなさい。

<p class="aaa">要素1</p>
<p class="aaa bbb">要素2</p>
<p class="ccc aaa bbb">要素3</p>
<p class="aaa ccc bbb">要素4</p>
<p class="aaa bbb">要素5</p>

要素1

要素2

要素3

要素4

要素5





内容:

繰り返し

目標

プログラミングにおいては、条件分岐に並んで大事な制御に、繰り返しがある。
ここでは、JavaScriptの繰り返しについて学ぶ。
また、これまで何となく使ってきたブロックについて理解する。

  • 文とブロックについて理解する。
  • while文の挙動を理解することができる。while文を正しく書くことができる。
  • for文の挙動を理解することができる。for文を正しく書くことができる。
  • while文で書かれた繰り返しをfor文で書き直すことができる。
  • for文で書かれた繰り返しをwhile文で書き直すことができる。
  • continue文を使った繰り返しの挙動を理解できる。continue文を正しく使うことができる。
  • break文を使った繰り返しの挙動を理解できる。break文を正しく使うことができる。

文とブロック

前回、if文では次のような構文が使われると紹介した。
このif文の例では、波括弧「{」および「}」で囲まれた部分が実行されたりされなかったりする。

if (条件1) {
  /*
   *  条件1が成立する場合のみ実行される処理ブロック
   */
} else if (条件2) {
  /*
   *  条件1が成立せず、条件2が成立する場合のみ実行される処理ブロック
   */
} else if (条件3) {
  /*
   *  条件1〜条件2が成立せず、条件3が成立する場合のみ実行される処理ブロック
   */
...
} else if (条件n) {
  /*
   *  条件1〜条件n-1が成立せず、条件nが成立する場合のみ実行される処理ブロック
   */
} else {
   /*
    *  どの条件にも当てはまらない場合のみ実行される処理ブロック
    */
}

しかし、実はこの表現は必ずしも正しくない。
JavaScriptでは本来、if文の構文は次のようになっており、この「文」とされているところに実行したい文を記述する。

if (条件1)
  条件1が成立する場合のみ実行される文
else if (条件2)
  条件1が成立せず、条件2が成立する場合のみ実行される文
else if (条件3)
  条件1〜条件2が成立せず、条件3が成立する場合のみ実行される文
...
else if (条件n)
  条件1〜条件n-1が成立せず、条件nが成立する場合のみ実行される文
else
  どの条件にも当てはまらない場合のみ実行される文

JavaScriptでは、波括弧「{}」で括られた部分は1つの文として扱われるという約束がある。
そのため、初めに示したような書き方が可能となっている。
逆にいうとif文は波括弧を使わずに次のように書くことができるということである。
この例では、変数nが偶数なら「偶数です」、そうでなければ「奇数です」というメッセージを表示する。

if (n % 2 == 0)
  alert("偶数です");
else
  alert("奇数です");

繰り返し

while文

基本的な繰り返しのための制御文としてwhile文を紹介する。
while文はある条件が成り立っている間、処理を繰り返すものである。
書式は次のとおりである。

while (条件) 
   条件が成立する間、実行を繰り返す文

もちろん、次のように書くこともできる。

while (条件) {
  /*
   *  条件が成立する間、実行を繰り返す処理ブロック
   */
}

書式は単純なif文に良く似ている。
実際、「条件」の所に書く式はif文で使った条件式と同じものである。
while文では、まず条件を評価し、その条件が成立したら中括弧でくくられたブロックを実行する。
ここまでは動作もif文と同じである。
ただし、中括弧でくくられたブロックを実行し終わると、閉じ中括弧の後ろを実行するのではなく、一旦、条件の評価に戻る。
ここがif文と異なる所である。
フローチャートで描くと次のようになる。

while文の動作

では、実際に簡単な例を使って動作を確認してよう。
下記は、1から始めて順に値を2倍にして表示していくプログラムである。
値が100未満である限り繰り処理を返します。

var n = 1;
while (n < 100) {
  alert(n);
  n = n * 2;
}


このプログラムでは、始めにnを1にした後にwhile文に入る。
while文の中ではnが100より小さい場合には、まずその数字をポップアップで表示し、その後nを2倍して次の回に備える。
while文を1回目に実行する時はnは1だが、そのwhile文が終わる時には「n = n * 2」によってnが2倍され2になる。
nが2でも100よりは小さいので、もう一度while文の中括弧でくくられたブロックが実行される。
ここでは2と表示をした後に、再び「n = n * 2」が実行されnが4になる。
その後、nが128になるまで同じ部分が繰り返される。
nが128になった時点で2行目のwhile文の条件が成立しなくなるので、while文の後のブロックを抜け、プログラムは終了する。

繰り返し条件を間違えると延々と同じことが繰り返され、プログラムが終了しない状態になることがある。
このような状態のことを「無限ループ」と表現したりする。
無限ループ状態になると、ブラウザが応答しなくなるかもしれない。
このような場合は、一旦ブラウザを終了する。
キーボードの「command」「option」「esc」の3つのボタンを同時に押すと「アプリケーションの強制終了」画面が開くので、ここでブラウザを指定して終了する。
ブラウザを再起動した後に同じページを開いてしまうと、また無限ループに入ってしまうので、ページを開く前に当該ページを修正しなければならないことに注意が必要である。

do-while文

do-while文は、while文と似たような動作をするが、条件を評価する場所が異なる。
下記にdo-while文の書式を示す。

do 
  1回目と、条件が成立する間、実行を繰り返す文
while (条件);

下記のフローチャートをみて欲しい。
これはdo-while文のフローチャートである。
while文と比べると、条件を評価する部分が処理の下になっていることがわかる。
このため、do-while文を使うと、最低でも1回は処理が実行されるループを作る事が可能である。

do-while文の動作

do-while文はwhile文に比べると、あまり使われる頻度は多くない。
アルゴリズムにおいて、最低でも1回は実行しなければならないという状況が少ないためである。

for文

繰り返しを使う場合、ある変数をカウンタとして利用することが多々ある。
このような場合に便利なのがfor文である。
for文は、while文ではバラバラに書かなければならなかった、A.変数の初期化、B.条件、C.カウンタの操作、の3つをまとめて書けるような構文を提供している。
下記の2つ構文をみて欲しい。
これらは完全に等価なものである。

while文を使った例
A.初期化
while (B.条件) {
  /*
   *  条件が成立する間、実行を繰り返す処理ブロック
   */
  C.カウンタの操作;
}
for文を使った例
for (A.初期化; B.条件; C.カウンタの操作)
   条件が成立する間、実行を繰り返す文

それぞれを、具体的な例で書くと下記のようになる。

while文を使った例
var i = 0;
while (i < 10) {
  alert("ここが繰り返される。");
  i++;
}
for文を使った例
for (var i=0; i<10; i++)
   alert("ここが繰り返される。");

これはどちらもi=0からi=9まで10回処理ブロックを実行するというものである。
ここではfor文の「A.初期化」の部分でvarを使って同時に変数を定義しているが、これは次に示すように繰り返しの外側で行われても構わない。

var i;
for (i=0; i<10; i++) {
  /*
   *  条件が成立する間、実行を繰り返す処理ブロック
   */
}

また、for文の構文の中に「C.カウンタの操作」とあるが、ここには代入文を書く事も可能である。
例えば、カウンタを0、2、4、6、8と進めたければ次のように書くことができる。

for (var i=0; i<10; i=i+2) {
  /*
   *  条件が成立する間、実行を繰り返す処理ブロック
   */
}

i=i+2」は「i+=2」でも同じ意味になる。

カウンタを減らしていくことも可能である。
10、8、6、4、2のようにしたければ、次のように書く。
この例でも「i=i-2」を「i-=2」と書き直すことが可能である。

for (var i=10; i>0; i=i-2) {
  /*
   *  条件が成立する間、実行を繰り返す処理ブロック
   */
}

繰り返しの制御

繰り返しを使っていると、途中で繰り返しを止めたくなったり、今すぐに次の回に入りたくなったりすることがある。
このような時のためにJavaScriptでは、break文とcontinue文を提供している。

break文

繰り返しを途中で止めたい場合、break文を使うことによって条件に関係なく繰り返しから脱出することができる。

次のプログラムを見て欲しい。
このプログラムは、「男」または「女」という文字を10個入力し、それぞれの入力された回数を表示するものである。

var male = 0;
var female = 0;
for (var i=0; i<10; i++) {
  var gender = prompt("「男」または「女」を入力してください。");
  if (gender == "男")
    male = male + 1;
  else
    female = female +1;
}
alert("男性" + male + "人、女性" + female + "人です。");


この例では、必ず10個の文字を入力しなければならない。
これを途中で止められるようにするためにはどうすれば良いだろうか。
例えば、文字列「end」を入力すると、そこまでの合計を表示するようにするには次のようにする。

var male = 0;
var female = 0;
for (var i=0; i<10; i++) {
  var gender = prompt("「男」または「女」を入力してください。");
  if (gender == "end") break;
  if (gender == "男")
    male = male + 1;
  else
    female = female +1;
}
alert("男性" + male + "人、女性" + female + "人です。");


continue文

上の例では、「男」「end」以外の文字列を入力すると、女性としてカウントされてしまう。
ここで、「男」「女」「end」以外の文字列が入力されたらどちらにもカウントされないようにしたい。
そのためには、if文のelse節をelse ifにする方法もあるが、次のようにすることもできる。

var male = 0;
var female = 0;
for (var i=0; i<10; i++) {
  var gender = prompt("「男」または「女」を入力してください。");
  if (gender == "end") break;
  if (gender != "男" && gender != "女") continue;
  if (gender == "男")
    male = male + 1;
  else
    female = female +1;
}
alert("男性" + male + "人、女性" + female + "人です。");


この例ではcontinue文を用いることにより、「男」でも「女」でもない文字列が入力された場合には、カウント動作をせず、次の繰り返しに入るようになっている。
ここで、文字列「end」かどうかを調べる文の後に、continue文を含むif文があることに注意が必要である。
逆の順番だと、文字列「end」が入力されても、「男」でも「女」でもないので、繰り返しの先頭に戻ってしまう。

練習問題4-

while文を用いて、0から10までの数字の中で、偶数のみを「0, 2, 4, 6, 8, 10」とアラート表示するプログラムを作成しなさい。


練習問題4-

for文を用いて、0から10までの数字の中で、奇数のみを「1, 3, 5, 7, 9」とアラート表示するプログラムを作成しなさい。


練習問題4-

モンテカルロ法でN回試行し、円周率を求めるプログラムを作成しなさい。
ただし、N=100とする。また、基本的なモンテカルロ法での円周率の求め方は以下のとおりである。

  1. mを0にする。
  2. 1×1の範囲の任意の点(x,y)に点を打つ。
  3. その点の原点からの距離( SQRT(x2+y2))が1以下ならmに1加える。(ヒント:不等式の両辺を二乗しても同じなので、x2+y2が1以下であれば良い。)
  4. 2〜3をN回繰り返す。
  5. 1/4円の面積はπr2/4で、上記の場合r=1なのでπは4m/Nで求められる


練習問題4-

上記のモンテカルロ法のプログラムで、試行回数をプロンプトから入力できるようにしなさい。

入出力と条件分岐

目標

ここではプログラムの流れを条件によって変える、条件分岐について学ぶ。
条件分岐はプログラミングにおいて、基本的な要素の1つである。
また、初歩的なプログラムへの入出力インターフェイスとしてalert()及びprompt()、乱数を発生させるためのMath.random()について学ぶ。

  • 正しくprompt()関数を使い、変数に値を入力することができる。
  • 正しくalert()関数を使い、変数も使いながらメッセージを表示することができる。
  • 乱数を使ったプログラムを作成することができる。
  • 正しく単体の条件式が書ける。
  • 論理演算子を用いて複数の条件式を結合することができる。
  • if文の挙動を理解することができる。if文を正しく書くことができる。
  • if-else文の挙動を理解することができる。if-else文を正しく書くことができる。
  • else if節の挙動を理解することができる。else-if節を正しく書くことができる。
  • switch文の挙動を理解することができる。switch文を正しく書くことができる。

alert()とprompt()

プログラムにおいて、ユーザからの入力を得たり、ユーザに対してメッセージを発したりすることは頻繁に行われる。
ここでは、ブラウザとJavaScriptを使った一番簡単な入力と出力の方法であるprompt()とalert()について紹介する。

prompt()

prompt()関数は、ポップアップによってユーザからの入力を促し、入力値を返す関数である。
prompt()関数はカッコの中に値を1つ入れることができ(「引数を1つとる」と表現する)、その値をメッセージとしてポップアップで表示する。
また、同時に入力用のエリアが表示され、そこに値を入力できる。
入力した値は、関数が返す値となる。
ここで値は文字列として返されるので、数字を入力するような場合には注意が必要である。

次の例では、値を入力するためのポップアップを「あなたの名前は?」というメッセージと共に表示し、入力を促す。
入力された値は、変数yournameに格納される。

...
var yourname = prompt("あなたの名前は?");
...

alert()

alert()関数は、ポップアップによってメッセージを表示するための関数である。
alert()関数は引数を1つとり、その値をメッセージとしてポップアップで表示する。
実際の使い方の例を下記に示す。

...
alert("Hello World!");
...

この例では、文字列リテラルで表現された文字列を単純にポップアップとして表示させている。
一方で、alert()の括弧の中には式を書くこともできる。
式を書くとその評価された値がポップアップとして表示される。

...
var yourname = "taro"; 
...
alert("Hello " + yourname);
...

prompt()とalert()を使った例

次の例は、prompt()alert()を使った例である。
この例では、始めの行で名前を入力させ、入力した名前を変数yournameに格納している。
その上で、名前に続けて「さん、こんにちは」というメッセージをポップアップで表示している。

...
var yourname = prompt("あなたのお名前は?")
alert(yourname + "さん、こんにちは");
...

上記のプログラムが実際に動作する例を次に示す。
ボタンを押してみて欲しい。

さて、次のプログラムを見て欲しい。
このプログラムはどのように動作するであろうか。

...
var num1 = prompt("1つ目の値を入力してください。");
var num2 = prompt("2つ目の値を入力してください。");
alert(num1 + num2);
...

おそらく意図としては、数値を2つ入力してもらい、それぞれ変数num1と変数num2に格納し、その和を表示したいのであろう。
しかし、実際にはそのようにはならない。
実際に動作するボタンを下記に示すので、試してみて欲しい。

実際にやってみて気づくと思うが、入力した2つの値は数値ではなく文字列として扱われてしまっているため、演算子+が文字列同士の足し算、つまり文字列の連結として解釈されてしまっている。
数値の足し算がしたい場合には、文字列を数値に変換する必要がある。
Number()を使って次のようにすると、想定どおりに動作する。

...
var str1 = prompt("1つ目の値を入力してください。");
var str2 = prompt("2つ目の値を入力してください。");
var num1 = Number(str1);
var num2 = Number(str2);
alert(num1 + num2);
...

動作例を次に示す。

乱数

乱数とは

プログラムは、コンピュータに行わせる処理を記述するものである。
基本的には、何らかの条件によって動作を変えたり、繰り返し同じ処理をさせたりすることを記述することによって、プログラム動作が決まる。
しかし、アルゴリズムの中には、モンテカルロ法のように無作為に選択された値(乱数)を必要とするものがある。
多くのプログラミング言語は、このような乱数を発生させるための機能を有している。

Math.random()

JavaScriptにおいて乱数を発生させるためには、Math.random()を用いる。
Math.random()は、Mathオブジェクトのrandom()メソッド呼び出しであるが、Mathオブジェクトについては別の回で説明する。

Math.random()は、呼び出されると、0以上1未満の数を返す。
どのような値が返ってくるかはその時々によって、異なったものとなる。

例えば次のプログラムを見て欲しい。
このプログラムでは、Math.random()を呼び出してその返り値を変数numに代入し、次の行でその値を表示している。
動作例のボタンを何度か押してみて欲しい。
押すたびに異なった値が表示されることがわかるだろう。

var num = Math.random();
alert("乱数の値は" + num + "でした。")

条件分岐の概要

プログラムを書いていると、入力された値などによってプログラムの動作を変えたくなることがある。
このような機能を実現するのが条件分岐と呼ばれるものである。
JavaScriptでは、条件分岐のためにif文とswitch文が用意されている。

条件式

比較演算

条件によってプログラムの動作を変えるためには、まず条件を記述する方法を覚える必要がある。
まずは、条件の記述方法についてみてこう。

多くのプログラミング言語には、ある式が成立する(真、true)か否(偽、false)かを返す種類の演算がある。
これが条件を記述する方法である。
つまり、条件を記述するためにも演算子を使った式が使われる。

まずは、比較演算子について説明する。
比較演算子はその名の通り、演算子の左右の値を比べて、式が成立するかどうかを判断する為の演算子である。
比較演算子には次のようなものがある。

演算子 意味 使用例
== 等値演算。左右の値が同じであるかを判断する。同じ場合には真、そうでない場合には偽を返す。 a == b、sum == 100
!= 不等値演算。左右の値が同じであるかを判断する。異なる場合には真、そうでない場合には偽を返す。 a != b、sum != 100
< 左の値が右の値より小さいかどうかを判断する。小さい場合には真、そうでない場合には偽を返す。 a < b、sum < 100
> 左の値が右の値より大きいかどうかを判断する。大きい場合には真、そうでない場合には偽を返す。 a > b、sum > 100
<= 左の値が右の値以下かどうかを判断する。以下の場合には真、そうでない場合には偽を返す。 a <= b、sum <= 100
>= 左の値が右の値以上かどうかを判断する。以上の場合には真、そうでない場合には偽を返す。 a >= b、sum >= 100

文字列の比較

文字列にも比較演算子を使う事ができる。
この場合は少し注意が必要である。
文字列の大小を比較する場合にはアルファベット順で比較される。
よって、「"3" < "5"」や「"12" < "3"」、「"abc" < "def"」はどれも真になる。
また、日本語の場合は少し複雑である。
コンピュータの内部では、文字は文字コード(JISやEUC、Unicodeといった複数のコードが存在しています)という番号によって表現されている。
文字は、この文字コードの順番によって大小決まる。
このため、あいうえお順にはならない事に気をつける必要がある。

論理演算子

より複雑な条件を記述するためには、幾つかの条件を組み合わせる必要がある。
例えば、ある数字numが3より大きくて10より小さいという条件を記述したい場合、「3 < num」と「num < 10」という二つの条件を満たさなければならない。
このような場合に、式を組み合わせるために論理演算子と呼ばれるものがある。
下記に論理演算子を挙げる。

演算子 意味 使用例 使用例の意味
&& 論理積。and演算。左右とも真の場合に真となる。 3 < num && num < 10 numが3より大きく、10より小さい
|| 論理和。or演算。左右のどちらか、あるいは両方が真の場合に真となる。 num < 3 || 10 < num numが3より小さいか、10より大きい
! 否定。not演算。評価する値が真の場合は偽を、偽の場合は真を返す。 !(num < 3) numが3より小さくない

ある数字numが3より大きくて10より小さいという条件を記述したい場合、上の論理積を使って「3 < num && num < 10」と書く。
3 < num < 10」の様には書くことはできないので、注意が必要である。

和差積商などの算術演算に優先順位があったように、論理演算にも優先順位がある。
論理演算の優先順位は優先順位が高い順に「!」、「&&」、「||」になっている。

論理演算にはいろいろな特徴がある。
例えば、否定の否定は肯定である。
論理演算を使うと「[比較演算]」は「!![比較演算]」と同じになる。
「以下」というのは「より大きいではない」ということである。
ゆえに「a<=b」は「!(a>b)」である。
また、論理演算には「ド・モルガンの法則」と呼ばれる有名な法則もある。
この中では、「!([比較演算1]&&[比較演算2])」は「![比較演算1]||![比較演算2]」と同じだということを保証している。
また同様に、「!([比較演算1]||[比較演算2])」は「![比較演算1]&&![比較演算2]」と同じである。

if文、if-else文

基本的なif文

一番基本的なif文の使い方は、ある条件が成り立つ時のみプログラムの一部分を実行するというものである。
次の図に示すのはフローチャートと呼ばれるもので、プログラムの流れを表す為の手法の一つである。
この図では、if文の流れを表している。
if文では、ある条件が成り立ったときのみ処理を行い、成り立たない場合にはなにもしない、というのが一番基本的な書き方である。

基本的なif文の動作のフローチャート
基本的なif文の動作

上図のような動作をするif文は次のように表記する。
if文の条件の括弧の中には、上で説明したような比較演算子や論理演算子を組み合わせて記述した条件式を記載する。
もし、その条件式が真の値を返すようであれば中括弧で囲まれた部分が実行される。
条件式が成り立たない場合、すなわち偽となるような場合には中括弧の中は実行されることなく、次の命令に進んでいく。

if (条件) {
  /*
   *  条件が成立する場合のみ実行される処理ブロック
   */
}

if文のelse節

上の基本的なif文では、条件が成立したときのみ中括弧でくくられたブロックが実行された。
しかし、いろいろなプログラムを書いていると、条件が成立する場合には処理1を、成立しなかった場合には処理2を実行したいといったことがある。
論理演算子!を使って逆の条件文を書き、処理2を実行するということもできるが、あまり賢い方法とは思えない。

このようなニーズを満たすために、JavaScriptのif文にはelse節が書けるようになっている。
else節を使う場合の記法は下記のとおりである。

if (条件) {
  /*
   *  条件が成立する場合のみ実行される処理ブロック
   */
} else {
  /*
   *  条件が成立しない場合のみ実行される処理ブロック
   */
}

フローチャートで示すと、下図のようになる。

else節付きif文の動作のフローチャート
else節付きif文の動作

else if

if文を使って更に条件を細かく指定することもできる。
「○○の時は○○○、そうでなく△△の時は△△△、そうでもなく□□の時は□□□、そうでもなく××の時は×××を実行する」といった具合である。
このような条件分岐を記述するためには下記のようにする。
このとき、上から順番に条件を確認していき、始めに当てはまったもののみが実行される。
もし、ある条件1(例: num < 10)が別の条件2(例: num < 100)にすっぽり当てはまる場合、条件1の方を先に書かないと条件1が実行されることは決してない。

if (条件1) {
  /*
   *  条件1が成立する場合のみ実行される処理ブロック
   */
} else if (条件2) {
  /*
   *  条件1が成立せず、条件2が成立する場合のみ実行される処理ブロック
   */
} else if (条件3) {
  /*
   *  条件1〜条件2が成立せず、条件3が成立する場合のみ実行される処理ブロック
   */
...
} else if (条件n) {
  /*
   *  条件1〜条件n-1が成立せず、条件nが成立する場合のみ実行される処理ブロック
   */
}

else ifは幾つつなげても構いまわない。
また、最後に「どの条件にも合致しなかった場合には○○を実行する」という部分を入れたい場合は次のようにする。

if (条件1) {
  /*
   *  条件1が成立する場合のみ実行される処理ブロック
   */
} else if (条件2) {
  /*
   *  条件1が成立せず、条件2が成立する場合のみ実行される処理ブロック
   */
} else if (条件3) {
  /*
   *  条件1〜条件2が成立せず、条件3が成立する場合のみ実行される処理ブロック
   */
...
} else if (条件n) {
  /*
   *  条件1〜条件n-1が成立せず、条件nが成立する場合のみ実行される処理ブロック
   */
} else {
   /*
    *  どの条件にも当てはまらない場合のみ実行される処理ブロック
    */
}

if文を使ったプログラムの例

では、if文を使った実際のプログラムの例を見てみよう。
下記のプログラムを見て欲しい。
HTML部分でボタンを押すと関数に飛ぶ部分は既出である。
JavaScriptにおいては、2行目でユーザからの入力を促し、その値を変数strに格納している。
ここで変数strに格納される値は文字列として扱われるため、次の行でNumber()を使って数値に変換し、改めて変数numに格納している。
その上で、5行目からif文を使って分岐を行っている。
5行目では、フォームに入力された値numを2で割り余りが0かどうかを調べている。
つまり、numが2の倍数かどうかを調べている。
もし、2の倍数の場合はその直後のブロックの中を実行する。
つまり、「2の倍数です。」というメッセージを表示する。
もし2の倍数でなかった場合は、8行目のelse ifへ飛ぶ。
ここでは、numが3の倍数かどうかを調べている。
3の倍数の場合には、2の倍数の時と同様にその直後のブロックを実行し、「3の倍数です。」というメッセージを表示する。
2の倍数でも3の倍数でもない場合は、最後のelse節に飛び、「2の倍数でも、3の倍数でもありません。」というメッセージを表示する。

HTML部分
<button onclick="iftest()">if文を使った例</button>
JavaScript部分
function iftest() {
  var str = prompt("数値を入力してください。");
  var num = Number(str);
 
  if (num % 2 == 0) {  
    // 2の倍数
    alert("2の倍数です。");
  } else if (num % 3 == 0) {  
    // 3の倍数
    alert("3の倍数です。");
  } else {
    // 上記以外なら
    alert("2の倍数でも、3の倍数でもありません。");
  }
}


上記のプログラムにおいて、「6」や「12」など、2の倍数でも3の倍数でもある数値を入力するとどうなるであろうか?
「2の倍数です。」と「3の倍数です。」の両方が表示されるであろうか。
プログラムは基本的に上から下にむけて実行されることを思い出して欲しい。
「6」や「12」が入力された場合には、まず5行目のif文で評価される。
「6」や「12」は2の倍数なので、このif文の条件式が成立し、「2の倍数です。」というメッセージが表示される。
一度条件に合致してしまったので、それ以降のelse ifやelseは飛ばされる。
よって、「6」や「12」など、2の倍数でも3の倍数でもある数値が入力された場合には「2の倍数です。」というメッセージのみが表示されることになる。

switch文

JavaScriptのもう1つの条件分岐のための仕組みは、switch文である。
switch文は式の評価結果がどのような値を取るかによって、複数の選択肢に分岐する制御分である。
同じ1つの式の評価結果によって複数の選択肢に分岐するような場合には、if文より簡単に記述できるため便利である。
逆に言うと、switch文で書くことができる条件分岐は、複雑にはなるがif文でも書くことができる。

次にswitch文を使った例を示す。
この例では、「朝」「昼」「夕」「夜」のいずれかをユーザに入力してもらい、入力によって挨拶の文言を変えている。
switch文の括弧の中にある式の値が、複数あるcase節の後の値のいずれかに合致すれば、その次の行のalert()関数から先が実行される。
実行している中でbreak文が現れると、そこでswitch文は終了する。
break文が無いと、そのまま次のcase節に続く部分まで実行されてしまうので注意してほしい。
例えば下の例では「夕」と入力すると、そのまま次の「case “夜”」の下にある部分が実行される。

また、どのcase節にも合致しなかった場合は、default節の次の行から実行される。

var word = prompt("朝/昼/夕/夜のいずれかを入力してください。");
switch (word) {
  case "朝":
    alert("おはようございます。");
    break;

  case "昼":
    alert("こんにちは。");
    break;

  case "夕":
  case "夜":
    alert("こんばんは。");
    break;

  default:
    alert("理解できません。");
}


練習問題3-

ボタンを押すと「今日の天気はなんですか?」というプロンプトが表示され、「晴れ」と入力すると「素敵な1日を!」、それ以外の入力をすると「今日も頑張りましょう!」とアラート表示されるプログラムを作成しなさい。

練習問題3-

「占う」というボタンを作り、ボタンを押して、乱数が0.1未満だったら「凶」、0.1以上0.33未満だったら「小吉」、0.33以上0.66未満だったら「中吉」、0.66以上だったら「大吉」とアラート表示されるプログラムを作成しなさい。

練習問題3-

2つのボタンを作って、1つは条件分岐をif-else文で、もう1つはswitch-case文で下記のプログラムを作成しなさい。

ボタンを押すと「今日の夕飯の気分を 洋食/和食/中華/その他 で答えてください」というプロンプトが表示され、
それぞれの入力に応じてお勧めのレストランをアラートで表示する。

練習問題3-

ボタンを押すと「曜日は?」というプロンプトが表示され、
そこに曜日を入力すると、次に「時限は?」というプロンプトが表示され、
時限を入力すると、自分が履修している科目がアラートで表示されるプログラムを作成しなさい。
ただし、何も履修していない曜日時限が入力された場合は、「何も履修していません」というアラートを表示しなさい。