sit in a circle and chat happily

JavaScript 16日目

投稿日:2021-12-23
更新日:2022-03-24
js

第13章:関数

関数(fanction)とは

よく使う処理をまとめたもの。
一度定義してしまえばいつでも呼び出して使える。

関数の使いどころ

・よく使う処理
・イベントと紐づけた処理
  (例:ボタンを押したら実行)

関数は「定義」と「呼び出し」

関数はよく使う処理をあらかじめ定義(記述)しておく。
必要になったら呼び出す。こうすることで同じ処理を何度も書く必要がなくなり、修正する際も関数定義部分を変更すれば呼び出しているすべての場所に変更が反映される。

関数は定義していないと呼び出せない。また、定義済みでも呼び出さなければ何もしない。

関数名のつけ方

命名規則に則っていれば自由につけられる。関数の処理内容を予測できるような名前が良い。複数の単語をつなげて名前をつける場合はキャメルケース記法(2単語目以降先頭大文字)やスネーク記法(アンスコで単語をつなげる)が使われる。
パスカル記法(すべての単語の先頭大文字)はオブジェクト名と混同するので使わない。

関数のバリエーション

関数は状況に応じて以下の4種類を使い分けて定義する。

①引数なし・戻り値なし関数

呼び出すといつも同じ処理をする(完結型)

引数なし・戻り値なし関数の定義

function 関数名(){
  呼び出された時に実行する処理
}

引数なし・戻り値なし関数の呼び出し

関数名()
// functionキーワードから始まる記述が関数定義部分
// ◆呼び出された時に実行される
function attack() {
  console.log('攻撃した!!');
}
function guard() {
  console.log('防御している・・・');
}

console.log('1回目の出力');
// 関数の呼び出し
attack();
guard();
コンソール出力内容

②引数あり・戻り値なし関数

関数に渡した値を使って処理する(完結型)

引数あり・戻り値なし関数の定義

function 関数名(引数 値受け取り用){
  呼び出された時に実行する処理
}

引数あり・戻り値なし関数の呼び出し

関数名(引数 関数に渡す値)
// 関数定義:引数あり
// 呼び出された時に【引数を受け取って】から
// 関数内の処理を実行
// 関数内で【受け取った引数】を自由に使える

function attack(name = 'NO name') {
  console.log(name + 'は攻撃した!!');
}
function guard(name) {
  console.log(name + 'は防御している・・・');
}
// 複数の引数を受け取る場合は
// カンマ区切りの受け取り用の引数を用意
function magic(name, magicName) {
  console.log(name + 'は' + magicName + 'を唱えた!');
}

console.log('1回目の出力');
// 関数の呼び出し
// 呼び出し時、定義部分に渡す値を
// 引数部分に記述
attack('田中');
guard('佐藤');
attack('鈴木');
// 引数を渡さなかった場合は
// 「undefined(空)」を渡す
// 定義側にデフォルト値を設定していると
// 「undefined」ではなく「デフォルト値」が入る
// 例)function attack(name = '名無しさん')
attack();
// 引数を複数指定可能
// カンマ区切りで値を渡す
magic('田中', 'メラミ');
コンソール出力内容

③引数なし・戻り値あり関数

呼び出すといつも同じ処理をして結果を返す

戻り値

return文を記述することで戻り値ありの関数を作成できる。関数内のreturn文が実行されると値を関数呼び出し元に返す。

もしreturn文が関数内処理の途中に記述されていた場合は、return文の処理業で関数の実行を終了し、以降の関数内処理は実行されない。

関数内の処理結果を関数外に渡すことで連続性のあるプログラムを記述できる。

引数なし・戻り値あり関数の定義

function 関数名(引数 値受け取り用){
  呼び出された時に実行する処理
  return 戻り値
}

引数なし・戻り値あり関数の呼び出し

関数名()
// 関数定義
function enemy() {
  console.log('ダメージを受けた!!');
  var point;  // ダメージポイント用変数
  point = Math.random() * 100;
  // 乱数を使って0以上100未満の数値(小数アリ)を代入
  point = Math.ceil(point);
  // 切り上げ処理で0以上100までの整数を代入
  console.log(point);
  // ダメージポイントをコンソール表示
  return point;
  // 戻り値の指定
  // 関数呼び出し部分に値を戻す
}
var life = 1000;

console.log('1回目の出力');
life -= enemy();
// 1.減算代入使用とするが右辺未確定のため保留
// 2.enemy関数を引数なしで呼び出し

// 3.関数内を処理して値が戻る ★右辺が確定
// 4.保留になっていた減算代入処理を実行
//   life -= 戻り値;
console.log(life);

// ◆引数
//    関数外から関数内に値を渡す方法
// ◆戻り値(返り値)
//    関数内から関数外に値を渡す方法
コンソール出力内容
処理順
// 関数定義
function recovery() {
  var num = Math.random();
  // 乱数を使って0以上1未満の数値(小数アリ)をnumに代入
  console.log(num);
  // 確認のため変数numを出力
  if (num > 0.8) {
    console.log('大回復した');
    return 500;
    // return以降の処理はすべて実行されない
    // 即関数呼び出し部分に戻り値を持って戻る
  }
  console.log('回復した');
  return 200;
}
var life = 1000;

console.log('2回目の出力');
life += recovery();
console.log(life);
コンソール出力内容
処理順

④引数あり・戻り値あり関数

関数に渡した値を使って処理をして結果を返す

引数あり・戻り値あり関数の定義

function 関数名(引数 値受け取り用){
  呼び出された時に実行する処理
  return 戻り値
}

引数あり・戻り値あり関数の呼び出し

関数名(引数 関数に渡す値)
function enemy(name) {
  // 1回目の出力:引数name → '田中'
  var point;
  point = Math.random() * 100;
  point = Math.ceil(point);
  // point = 0以上100以下の整数を代入
  console.log(name + 'は' + point + 'ダメージを受けた!!');
  // 「田中は【pointに入った乱数】ダメージを受けた!!」
  // をコンソールに出力
  return point;
  // 乱数を関数呼び出し元に渡す
}
var playerList = [
  { name: '田中', life: 1000 },
  { name: '佐藤', life: 500 },
];

console.log('1回目の出力');
playerList[0].life -= enemy(playerList[0].name);
// 田中のライフ -= enemy('田中');
// 田中のライフ -= 戻り値【乱数】
console.log(playerList[0].life);
コンソール出力内容
function recovery(name, magicID) {
  // name:'田中'  名前
  // magicID:1  魔法ID番号
  var magicName;  // 日本語の魔法名
  var point;  //ダメージポイント
  // 関数内で変数宣言しないと「グローバル変数」として扱われる
  // ※バグの温床になりやすいため、なるべく関数内で宣言をする方が望ましい
  // 詳細は次の章で確認していく
  switch (magicID) {
    case 1:
      magicName = 'ホイミ';
      point = 100;
      break;
    case 2:
      magicName = 'ベホイミ';
      point = 200;
      break;
    case 3:
      magicName = 'ベホマズン';
      point = 300;
      break;
  }
  console.log(name + 'は' + magicName + 'を唱えた!' + point + '回復');
  return point;
}

var playerList = [
  { name: '田中', life: 1000 },
  { name: '佐藤', life: 500 },
];

console.log('2回目の出力');
playerList[0].life += recovery(playerList[0].name, 1);
// 田中のライフ += recovery('田中',1)
// 田中のライフ += 戻り値【乱数】;
console.log(playerList[0].life);
コンソール出力内容

【問】playerList[]の部屋番号を変数にすると少し効率化できる

// 問題
console.log('◆問1:佐藤さんに攻撃!');
var playerNum = 1;

playerList[playerNum].life -= enemy(playerList[playerNum].name)

console.log('◆問2:佐藤がベホイミ→佐藤を回復');
playerNum = 1;
var receivePlayerNum = 1;
playerList[playerNum].life += recovery(playerList[playerNum].name, 2);
console.log(playerList[receivePlayerNum].name + 'のHP: ' + playerList[receivePlayerNum].life);


console.log('◆問3:田中がベホマズン→佐藤が回復');
playerNum = 0;
receivePlayerNum = 1;
playerList[receivePlayerNum].life += recovery(playerList[playerNum].name, 3);
console.log(playerList[receivePlayerNum].name + 'のHP: ' + playerList[receivePlayerNum].life);
コンソール出力内容

巻き上げ(ホイスティング)

プログラム実行前に変数宣言と関数宣言が事前に読み込まれる(コードの一番上に移動するイメージ)ことを巻き上げ(ホイスティング)と呼ぶ。

関数宣言(関数定義部分)はプログラム実行前に読み込まれているため、
関数定義が関数呼び出しより下に記述されていても問題ない。

関数定義はプログラムの上、もしくは下にまとめて記述されることが多い。

// 変数宣言部分と関数定義部分は
// ファイル上部に巻き上げられてPG処理が開始する
// 下部に記述されていても、問題は起きない
// 【イメージ】
// var num2;
// function test() {
//   var num1 = 100;
//   console.log('関数内:' + num1);
// }

console.log('1回目の出力');
test();

console.log('2回目の出力');
console.log('変数宣言前:' + num2);
var num2 = 200;
console.log('変数宣言後:' + num2);

console.log('3回目の出力');
console.log('変数宣言無し:' + num3);

function test() {
  var num1 = 100;
  console.log('関数内:' + num1);
}
コンソール出力内容
これはホイちゃん
カテゴリー