ノンプロ研 GAS初級講座21期 補講 #2-3

# 概要
**ノンプログラマーのためのスキルアップ研究会 GoogleAppsScript初級講座**
第2回「制御構文」
第3回「関数・配列」
についての**非公式**の補講記事です。
21期講師のTaitoが執筆しています。

https://plannauts.co.jp/nonproken/

2回分をまとめてみたら、とても長い分量になってしまいました。反省しています！
ざっと眺めていただいて、気になったところは直接ご質問くださいませ。

# 第2回 制御構文

### ここだけ覚えるポイント
- プログラムの`実行順`を`制御`する書き方
- `条件式`(true false)で判定する
    - ずーみんTAの言う「条件式は門番のようなもの」がわかりやすいです！
    - 論理演算子で拡張
        - && かつ
        - || または
-  `選択処理` - if文 switch文
    -  分岐
    - 上から順に条件式を評価、最初にマッチしたブロックを実行
- `反復処理` - for文 while文
    - 繰り返し
    - ループ毎に条件式を評価、falseなら終了
- `if文`と`for文`が書ければOK

#### 条件式について(補足)
条件式は変数に入れられます。
うまく使うと、コードの可読性が上がります。
```javascript
const fizz = i % 3 === 0;
const buzz = i % 5 === 0;
if(fizz && buzz) {
  console.log('FizzBuzz'); // iが3と5で割り切れる時に実行
} 
```

条件式は暗黙の型変換をするので、
trueに変換される(`truthy`)値、falseに変換される(`falsy`)値も利用できます、
が、一見して分かりづらいコードになることが多いので、乱用は厳禁です。
```javascript
// iは1以上でtrue、0でfalseに変換され、ループを停止します
for(let i = 3; i; i--) {
  console.log(i);
} // 3, 2, 1

for(let i = 3; i > 0; i--) { // 素直に書いたほうが何をしてるかわかりやすい
  console.log(i);
} // 3, 2, 1
```
#### (もっと発展)===厳密等価と==等価の違い
条件式を==で書くと暗黙の型変換をされてしまい、不都合が多いです。
まったく違うデータである筈の以下の条件式がtrueになってしまいます。
```javascript
1 == [1]; // true
0 == ''; // true
[[]] == false; // true
```
対照表はこんな感じです。
覚える必要はありません。ちゃんと===を使えばOKです！

https://dorey.github.io/JavaScript-Equality-Table/

* * *

### 選択処理

#### if文
```javascript
if(条件式A) {
  // 条件式Aがtrueなら実行
} else if(条件式B) {
  // 条件式Bがtrueなら実行
} else {
  // その他の場合実行
}
```
#### switch文
```javascript
switch(式) {
  case 値A:
    // 式 === 値Aがtrueなら実行
    break;
  case 値B:
    // 式 === 値Bがtrueなら実行
    break;
  default:
    // いずれにもあてはまらなければ実行(省略可)
}

/** こうも書けます */
switch(true) {
  case 条件式A:
    // true === 条件式A つまり条件式Aがtrueなら実行
}
```

#### (ちょっと発展)ifとswitchの使い分け
条件分岐はif文で書くのが一般的ですが、場合によってはswitchを優先することもあります。
- 分岐がシンプルで、且つ多岐にわたる時
- 複数の条件に同じ処理を入れたい時
    - breakを省略した`フォールスルー`という書き方があります
    - 実践で使うことはほぼありません
```javascript
const rank = '優';
switch (rank) {
  case '優':
    console.log('成績上位者です!');
    // breakを省略すると、breakが出てくるまで実行を続ける
  case '良':
  case '可':
    console.log('合格です');
    break;
  case '不可':
    console.log('不合格です');
    break;
}
```
* * *
### 反復処理

#### for文
```javascript
for(初期化式; 条件式; 増減式) {
  // 処理
}
/**
 *  初期化式→条件式→処理→増減式
 *         →条件式→処理→増減式... と繰り返します
 *  条件式がfalseになると終了
 */
```
#### while文
```javascript
初期化式;
while(条件式) { // 条件式がfalseになると終了
  // 処理
  増減式;
}
```
条件式が最終的にfalseになるように、
増減式で変化する値を、条件式に組み込んであげる必要があります。

#### (ちょっと発展)forとwhileの使い分け
- ループ毎に増減式を実行して、次のループにうつる
- 条件式で終了判定をする

という構造は同じです。なので、互いに同じことができます。
どちらでもよければ、for文で書くのが一般的かな？と思います。
求めている処理に対して見やすい書き方を選びましょう。

```javascript

/** for文はループ設定が1箇所にまとまってて見やすい */
for(let index = 0; index < array.length; index++) {
  // 配列の最初から最後までループする処理
}

/** while文はループ回数が決まっていない時に見やすい */
while(files.hasNext()) { // filesオブジェクトが次のファイルを持っている限り続ける
  file = files.next(); // 次のファイルを取り出す(増減式)
  // 処理
}

/** 構造を理解すれば、while文みたいなfor文も書けます */
let i = 1; // 初期化式
for( ;i <= 3; ) { // 条件式 ()内はどの式も省略可
  console.log(i);
  i++; // 増減式
} // 1, 2, 3
```
#### (もっと発展)breakとcontinue
ループ処理はbreakとcontinueで処理を止めることができます。
- `break` ループ全体を終了する
- `continue` そのループの処理のみ終了し、次のループに移る

`VLOOKUP関数`などと同じで、1つ値が見つかったらそこで処理を止める、みたいな感じです。
要所要所でよく使うので、憶えておきましょう！

```javascript
  for (let i = 1; i <= 5; i++) {
    if (i === 3) continue; // 3はスキップ
    console.log(i);
  } // 1, 2, 4, 5

  let j = 1;
  while (j <= 5) {
    if (j === 3) break; // 3で終了
    console.log(j);
    j++;
  } // 1, 2

  /** NOTE: if文は処理が1行であれば{}を省略できます */
```
#### (もっともっと発展)様々な省略記法(ショートハンド)
- if文の省略記法 3項演算子
- 暗黙の型変換
- for文の構造理解

こういった発展要素を全部盛りすると、
宿題のFizzBuzz問題はこんな風にも書けます。
```javascript
for(let i=1;i<=15;console.log(!(i%15)?'FizzBuzz':!(i%3)?'Fizz':!(i%5)?'Buzz':i),i++);
```
初めて見た時は何じゃこりゃー、と思いました。
これが書けるようになる必要は`まったくありません`し
こういうコードの書き方をするのは`人に伝わりづらい`ので非推奨ですが
知識として入れておくと、何かの際に役に立つこともあるかもしれません。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_Operator

# 第3回 関数・配列

### ここだけ覚えるポイント
- 関数
    - `プログラムの実行単位`
    - `引数を受け取って戻り値を返すもの`←NEW!
    - 関数リテラル、アロー関数の話は`一旦忘れましょう`
- 配列
    - たくさんのデータをまとめておける`連続した箱`
    - `インデックス(0始まりの番号)`を使ってアクセスする
- 関数も配列も入れ子にできる

### 関数
第2回まで関数はただの`実行単位`でしたが、
実は`引数を受け取って、戻り値を返す`という非常に重要な機能を持っています。
```javascript
/**
 * 1からnumまでを足した数を返す関数(こういうコメントがあると親切)
 * @param {number} num - 仮引数: 1からこの数まで足し合わせる
 * @return {number} sum - 戻り値: 合計値
 */
function getSum(num) {
  let sum = 0;
  for (i = 1; i <= num; i++) {
    sum += i;
  }
  return sum;
}

function myFunction3_02_02() {
  getSum(10); // ←1から10までを足した数 55 が戻ってきている

  // returnだけだとログ出力されないので、戻り値を確認する時はconsole.log()
  console.log(getSum(10)); // 55
}
```
この「引数と戻り値」の機能を使って、実に様々なことが出来るようになります。
楽しみにお待ちください！

#### (ちょっと発展)コード関数とシート関数
引数と戻り値の話は、Excelやスプレッドシートの関数を思い出すと腹落ちしやすいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2412979/5b1a1b45-06a7-b769-5343-84d06f244a18.png)
シート関数は、引数となるセルが変わると、別の結果を返します。
引数が違うと、同じ`処理`を使って、違った結果を返せるのが関数の強みです。

関数を書くこと === この`処理`を書くことです。
たとえば上のシート関数をコードで表現するとしたら、こうなります。
```javascript
function multiply(x, y) {
  return x * y;
}

function sum(numbers) {
  let result = 0;
  // 範囲を1次元配列にしてfor文で足し合わせます
  for(const number of numbers.flat()) {
    result += number;
  }
  return result;
}
```
なお、エディタに書いた関数はスプレッドシートから呼び出すこともできます。
こちらは講座第7回で紹介します。
* * *
### 配列
配列も、スプレッドシートと紐づけて考えるとわかりやすいです。
たとえばシートのこういう表は
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2412979/ef905995-4664-9e16-9093-11a235822e37.png)
2次元配列にするとこうなります。
```javascript
[ [ '名前', '年齢', '性別' ],
  [ 'Alice', 20, '女性' ],
  [ 'Bob', 30, '男性' ],
  [ 'Charlie', 40, '男性' ] ]
```
1行ごとが1次元配列で、全体が2次元配列になっていますね。
'Bob'にアクセスしたい時は、[インデックス]で指定します。
インデックスは0から始まるので、行列番号とは1ズレています。注意しましょう。
```javascript
const values = [
  [ '名前', '年齢', '性別' ],
  [ 'Alice', 20, '女性' ],
  [ 'Bob', 30, '男性' ],
  [ 'Charlie', 40, '男性' ]
  ];
console.log(values[2][0]); // Bob 3行目1列目(インデックス2,0)
```
#### for of文
急に出てきました、新しいfor文の書き方です。
超便利です。
```javascript
for(const record of values) {
  console.log(record);
}
// 以下順に出力されます
//  record -> [ '名前', '年齢', '性別' ]
//  record -> [ 'Alice', 20, '女性' ],
//  record -> [ 'Bob', 30, '男性' ],
//  record -> [ 'Charlie', 40, '男性' ]
```
for of文は`イテラブル(反復可能)`なデータに対して、
最初から最後までの要素を順にループする為の構文です。
for文のこの形が省略されているイメージです。
```javascript
for (let i = 0; i < values.length; i++) {
  const record = values[i];
  console.log(record);
}
```
for of文の書き方がわからない！という時は
一度通常のfor文で書いてみると、理解しやすいですよ！
* * *
2回分をまとめると、分量が大変なことになってしまいました…。
次回更新は2/7(火)の予定です。
引き続きよろしくお願いします！

### 参考書籍
https://www.amazon.co.jp/dp/4798064742