4日目:関数 (function) を作ってみよう。 – 1週間でプログラマーになろう。(毎日30分のプログラミング学習、入門講座)

プログラミング講座
cattle
cattle

本日は関数という物に触れてみましょう。まずは実際に使ってみる事で、どんな物なのか具体的なイメージが湧いて来ます。ご安心下さい。

途中からご覧になった方は、全体のロードマップをご確認頂けます。

わからない所があれば、ページ下部のコメント欄、又はtwitterからご相談頂けます。

前半 (15分) – 関数 (function) を作ってみよう。 – プログラミング学習、入門講座4日目

準備体操 (2分)

これまで通り、保存してあるスプレッドシートから、スクリプトエディタを開きましょう。やりかたを忘れた場合は、以下をご参考下さい。

前半(13分)- 関数 (function)を作ってみよう。

– 関数 (function) の要点
関数を使えば、処理のまとまりをわかりやすく管理出来ます。
更にその処理のまとまりを、必要に応じて簡単に呼び出せます。

まずは、実際に使ってみましょう。(10分)

エディタに記述されているこれまでのコード内容を全て削除します。(Ctrlキー + Aキーで全て選択されるので、Deleteキー、またはBackSpaceキーで削除します。)

次に、以下のコードを新しく記述します。

function myFunction() {
  console.log('モゥモゥ');
}

function testFunction() {
  console.log('ピヨピヨ');
}

これまで通り、Ctrlキー + Sキーで、修正内容を保存しましょう。

・エディタ左上から、実行 → 関数を実行 と選んでいきます。

これまで myFunction だけでしたが、testFunction が新たに増えました。

・試しに、myFunction を実行してみます。

ログの画像

※ ログに、モゥモゥが表示されました。

・次は、testFunction を実行してみます。

ログの画像

※ ログに、ピヨピヨが表示されました。

・今度は以下の様に、mainProc という新しいfunctionを追記してみましょう。

function myFunction() {
  console.log('モゥモゥ');
}

function testFunction() {
  console.log('ピヨピヨ');
}

function mainProc() {
  myFunction();
  testFunction();
}

・Ctrlキー + Sキーで修正を保存して、mainProc を実行して見ます。

ログの画像

※ モゥモゥ、ピヨピヨの両方が表示されました。

・更に、昨日鑑賞した文字ドラマを、このプログラムに組み込んでみましょう。

// 文字ドラマ関数の定義
function showDrama() {
  var name = '生まれたての子牛';
  
  console.log('『子牛の成長記録』');

  for(var age=0; age<5; age++) {
    if(age == 1){
      name = 'スクスク成長中';
    }
    if(age == 4){
      name = '母牛となり子牛を生みました。';
    }
    console.log('----------');
    console.log(age);
    console.log(name);
  }

  console.log('『~完~』');
}

// モゥモゥ関数の定義
function myFunction() {
  console.log('モゥモゥ');
}

// ピヨピヨ関数の定義
function testFunction() {
  console.log('ピヨピヨ');
}

// 実行する関数
function mainProc() {
  myFunction();    // モゥモゥ関数の呼び出し
  testFunction();  // ピヨピヨ関数の呼び出し
  showDrama();     // 文字ドラマ関数の呼び出し
}

・再び、Ctrlキー + Sキーで修正を保存して、mainProc を実行して見ます。

ログの画像

※ モゥモゥ、ピヨピヨ、更に文字ドラマをログに表示する事が出来ました。

・関数を実際に使ってみた事で、関数の大まかな要点を掴む事ができました。

– 関数 (function) メリットのまとめ

  • 処理のまとまりをわかりやすく管理できる。
  • それらを簡単に呼び出せる。
  • 機能ごとに関数化しておけば、プログラムの拡張性が増す。

関数 (function) を更に理解しましょう。(3分)

– 関数の作り方

function を使って、関数を定義します。

function 関数の名前() {
  この関数の処理を記述していきます。
}

関数の名前は、半角英数字を使って自由に決める事が出来ます。

– 関数は流用できる

処理のまとまりを自分でデザインしていきましょう。感覚を掴むのに少し慣れが必要ですが、上達するごとに開発速度がどんどん高まります。

function myFunction() {
  console.log('モゥモゥ');
}

function testFunction() {
  myFunction();
  myFunction();
  console.log('ピヨピヨ');
}

function mainProc() {
  testFunction();
  testFunction();
  myFunction();
}

mainProc関数の実行結果は以下となります。

ログの画像
cattle
cattle

前半はここまでです。お疲れ様でした。これまでに度々使ってきたconsole.log( )も関数です。後半を進めると、貴方もconsole.log( )の様に実用的な関数が作れるようになります。

後半(15分)- 実用的な関数の作り方 – プログラミング学習、入門講座4日目

関数に値を渡す(1分)

console.log関数の使い方を思い出してみましょう。

console.log('モゥモゥ');

( )の中に、’モゥモゥ’という文字列を書く事で、ログに’モゥモゥ’と表示される仕組みになっていましたね。これを関数の引数(ひきすう)と呼びます。

具体的には、console.log関数に対して、’モゥモゥ’という値を引数として渡す。と表現します。

全体的な処理の流れ(フローチャート)を掴もう(4分)

早速、引数を使った関数の全体的な流れを掴んで行きましょう。

以下のコードをエディタに記述して、mainProc関数を実行してみましょう。

function viewLog(val) {
  console.log(val);
}

function mainProc() {
  viewLog('モゥモゥ');
  viewLog('ピヨピヨ');
}
ログの画像
関数のフローチャート画像

以下は読むのが面倒ですが、処理の流れを完全に掴めます。

  1. スクリプトエディタがmainProc関数を実行します。
  2. mainProc関数が、ひとつ目のviewLog関数を実行します。(引数:’モゥモゥ’)
  3. viewLog関数は引数’モゥモゥ’を受け取り、変数valに値を代入します。
  4. viewLog関数の中で、console.log関数が変数valを引数として、実行されます。
  5. viewLog関数の{ }内の処理が全て終わり、mainProc関数に戻ってきます。
  6. mainProc関数が、ふたつ目のviewLog関数を実行します。(引数:’ピヨピヨ’)
  7. viewLog関数は引数’ピヨピヨ’を受け取り、変数valに値を代入します。
  8. viewLog関数の中で、console.log関数が変数valを引数として、実行されます。
  9. viewLog関数の{ }内処理が全て終わり、mainProc関数に戻ってきます。
  10. mainProc関数の{ }内処理が全て終わり、スクリプトエディタの関数実行処理が終了します。

引数への理解を更に深めよう(5分)

– 引数として、数値も渡せる。

function viewLog(val) {
  console.log(val);
}

function mainProc() {
  viewLog(100);
}
ログの画像

– 引数として、変数も渡せる。

function viewLog(val) {
  console.log(val);
}

function mainProc() {
  var price = 100;
  viewLog(price);
}
ログの画像

– 引数を複数定義出来る。

・引数を複数定義する場合は、, (カンマ) で区切ります。
・関数を呼び出して複数の引数を渡したい時も、同様に, (カンマ)で区切ります。
・console.log関数も、同様に複数の引数を渡すことが出来ます。
・複数個定義した引数は、定義された順に、第一引数, 第二引数, 第三引数, ・・・と呼ばれます。

function viewLog(age, name) {
  console.log('年齢:', age, '名前:', name);
}

function mainProc() {
  var myAge = 3;
  var myName = 'うし';
  viewLog(myAge, myName);
}
ログの画像

– 引数の初期値

ほぼ毎回同じ引数を渡す様なケースで、大変便利な機能です。

function viewLog(age, name = 'うし') {
  console.log("年齢:", age, "名前:", name);
}

function mainProc() {
  var myAge = 3;
  viewLog(myAge);
  myAge = 0;
  viewLog(myAge, '生まれたての子牛');
}
ログの画像
function viewLog(age, name = 'うし') {

引数を定義する際に、上記の様に『変数名 = 値』とする事で、変数の初期値を設定できます。

viewLog(myAge);

上記のviewLog関数の呼び出しでは、第二引数を省略しています。viewLog関数内の第二引数は初期値が使用されます。

viewLog(myAge, '生まれたての子牛');

この呼び出しでは、第二引数を省略せずに値を渡しています。viewLog関数内の第二引数は、初期値ではなく実際に渡した値が優先されます。

関数のよりスマートな使い方(5分)

関数内で、return という便利な機能を使うと、更に実用的な関数を作る事が出来ます。

関数returnのフローチャート画像

– return
上の図のフローチャートの様に、関数の呼び出し元に値を返す事ができます。関数内でreturnを実行した時点で呼び出し元(上の図ですとmainProc関数)に処理が戻ります。return をうまく扱えば無駄な処理を省けますので、品質の良いプログラムを書ける様になります。

より具体的なイメージを作る為に、以下を見て行きましょう。

// 価格を取得する関数
function getPrice() {
  return 100;
  console.log('モゥモゥ');  // 実行されない
}

// この関数を実行します。
function mainProc() {
  var price;
  price = 50;
  console.log(price);
  price = getPrice();
  console.log(price);
}
ログの画像

以下の部分で、returnされた値(戻り値と言います)を、変数priceに代入しています。

price = getPrice();

また、戻り値を関数の引数として直接利用出来ます。

console.log(getPrice());

関数の戻り値を利用して、更にコードを発展させて行くと、例えば以下の様な形になります。

// 価格を取得する関数
function getPrice(name) {
  var price;
  if(name == 'にわとり') {
    price = 100;
  }
  if(name == 'ぶた') {
    price = 200;
  }
  if(name == 'うし') {
    price = 500;
  }
  // 価格を返します。
  return price;
}

// この関数を実行します。
function mainProc() {
  var name;
  var price;
  
  // うしの価格を取得
  name = 'うし';
  price = getPrice(name);
  console.log(name, price);
  
  // にわとりの価格を取得
  name = 'にわとり';
  price = getPrice(name);
  console.log(name, price);
}
ログの画像

– 関数内で、複数のreturnを使えます。
同じ関数ブロック内で、returnを複数記述出来ます。しかし、return を多用し過ぎると、処理がどこで抜けていくのか分かり辛くなってしまうデメリットが存在します。関数を作っていく際には、出来る限りシンプルな設計を目指しましょう。

// 例外的な処理がある際は先に済ませると、returnが複数あっても理解しやすくなる。
function sellDrink(drinkName) {
  // if文のブロック内処理が一行だけの時は、以下の様にも記述可能
  if(drinkName == 'ビール') return 'お酒は年齢確認が必要です。';
  if(dringName == 'コーヒー') return 'お砂糖とミルクは必要ですか?';
  return '毎度ありがとうございました。';
}

– 変数のスコープ (非常に重要!)
定義された変数は、どこからでも自由に呼び出せるわけではありません。複数人で開発を行っていると、たまたま変数の名前が被ってしまって意図しないエラーが起きてしまいそうですよね? こういった問題が起きない様に、変数の呼び出しはあえて不自由な構造になっています。この仕組みを変数のスコープ(有効範囲)と表現します。

cattle
cattle

以前、{ } ブロックは、階層であると表現しました。この階層同士の関係性を整理する時、親子・兄弟・親戚関係に例えてイメージすると更に分かり易くなります。

// 親ブロック
function parent() {
  // 子ブロック
  function child() {
    // 孫ブロック
    function grandChild() {
    }
  }
  // 兄弟ブロック
  function brother() {
  }
}

// 親戚ブロック
function relatives() {
  // いとこブロック
  function cousin() {
  }
}

・変数は、それを定義した階層よりも上の階層からは呼び出せません。試しに、子ブロック内で変数nameを定義し、上の階層である親ブロックから呼び出してみましょう。

function parent() {

  // 変数nameを呼び出し
  console.log(name);

  function child() {
    // 変数nameを定義
    var name = 'cattle';
  }
}
変数のスコープ解説画像

※ 参照エラー:変数nameが未定義

・変数を定義した階層と同じ深さの階層であっても、ブロックが異なるとその変数は呼び出せません。

function parent() {
  function child() {
    // 変数nameを定義
    var name = 'cattle';
  }
  function brother() {
    // 変数nameを呼び出し
    console.log(name);
  }
  brother(); // brother関数実行
}
変数のスコープ解説画像

※ 参照エラー:変数nameが未定義

・変数を定義した階層よりも、下の階層であれば、その変数を呼び出せます。

function parent() {
  var name = 'cattle';
  function child() {
    console.log(name); //nameを呼び出し
  }
  child(); //child関数実行
}
変数のスコープ解説画像

・異なるブロックで、同名の変数をお互いにそれぞれ定義すると、それらは別の変数となります。(それぞれ別のアドレスを参照している。)

function showName(name) {
  console.log(name);
}

function parent() {
  var name = 'cattle';
  showName(name);
}

function relatives() {
  var name = 'うし';
  showName(name);
}

function mainProc() {
  parent();
  relatives();
}
ログの画像
cattle
cattle

本日はここまでです。おつかれさまでした。関数を上手に扱う為には、ある程度慣れが必要です。沢山失敗する事によって、こういう設計だとうまくいくのかと少しづつ感覚を掴んで行けます。時間がある時に他人の書いたプログラムを読んでみると、とても勉強になりますよ。

わからない所があれば、ページ下部のコメント欄、又はtwitterからご相談頂けます。

本日のまとめ

・関数を使ったプログラムの、大まかな処理の流れを理解出来ました。

・機能ごとに処理をまとめて、出来るだけシンプルな設計を心掛けましょう。

・引数、returnを扱えば、より実用的な関数が作れることを知りました。

次回、変数 (val) と 配列 (array) を理解しよう。

コメント