GASでプログラミング入門 Vol.6

# GASでプログラミング入門 Vol.6

社内サークルにてエンジニアから非エンジニアの方向けにプログラミングを教えるという活動を行っています。<br>
今回はその教材第6弾です。
前回の記事は[こちら](https://qiita.com/YoshinagaYuta/items/f2601cffc1aa1498557e)

## 前回の演習問題の解答例

(1). 引数を二つ受け取り、受け取った引数の計算結果を戻り値として戻す、関数 myPow を作成し、下記の表示になるようなプログラムを作成してください。

引数 1 が 2、引数 2 が 3 の時

```
2の3乗は8です。
```

引数 1 が 10、引数 2 が 2 の時

```
10の2乗は100です。
```

解答例コード

```js
/*
* 関数名：myFunction
* 概要：myPowを呼び出します
* 引数：ありません
*/
function myFunction() {
    let ans;
    let num1 = 2;
    let num2 = 3;
    ans = myPow(num1, num2);
    console.log(num1 + "の" + num2 + "乗は" + ans + "です。");

    num1 = 10;
    num2 = 2;
    ans = myPow(num1, num2);
    console.log(num1 + "の" + num2 + "乗は" + ans + "です。");
}
/*
* 関数名：myPow
* 概要：引数で受け取った数の冪乗を計算
* 引数：num1 冪乗計算の底
* 引数：num2 冪乗計算の冪指数
* 戻り値：num1のnum2乗した値
*/
function myPow(num1, num2) {
    return num1 ** num2;
}
```

(2). 引数を二つ受け取り、受け取った引数を文字列の戻り値として戻す、関数 myNameString を作成し、下記の表示になるようなプログラムを作成してください。

第一引数・・・苗字
第二引数・・・名前
戻り値・・・私の名前は`苗字 名前`です。

引数 1 が 鈴木、引数 2 が 一郎 の時

```
私の名前は鈴木 一郎です。
```

引数 1 が 山田、引数 2 が 花子 の時

```
私の名前は山田 花子です。
```

解答例コード

```js
/*
* 関数名：myFunction
* 概要：myNameStringを呼び出します
* 引数：ありません
*/
function myFunction() {
    let str = myNameString("鈴木", "一郎");
    console.log(str);
    str = myNameString("山田", "花子");
    console.log(str);
}
/*
* 関数名：myNameString
* 概要：引数で受け取った氏名を連結した文字列を作成
* 引数：苗字
* 引数：名前
* 戻り値：私の名前は苗字 名前です。
*/
function myNameString(arg1, arg2) {
    return "私の名前は" + arg1 + " " + arg2 + "です。";
}
```

なお解答例はあくまで例なので、必ずしも上記のようになっていないといけないわけではありません。

## 変数の有効範囲について

今まで触れてこなかった変数宣言の前に付けていた`let`キーワードについて紹介していきます。
まず`let`というのは変数の有効範囲に影響します。
下記のようなコードを用意し、実行します。

```js
function myFunction(){
    let num = 1; // 変数numはmyFunction関数の中でのみ有効
    console.log(num);
    myFunction2();
}
function myFunction2(){
    // 変数numはmyFunction2の中では宣言されていないので、無効
    console.log(num);
}
```

上記コードを実行すると`ReferenceError: num is not defined`というエラーが発生します。
これはmyFunction2関数では変数numを宣言していないので、エラーが発生しているよということを表しています。
このようにletは宣言されたブロック内でのみ有効な変数だよということを明示的にする為に使用されるキーワードです。
ここでいうブロックとは`{}`で囲まれた中のコードの事を表します。
ブロック内でということが重要で、例えば下記のようにif文の中で宣言した変数の有効範囲を見ていきましょう。

```js
function myFunction(){
    let num = 1;
    if (num == 1) {
        let num2 = 2; // 変数num2はif文のブロック内でのみ有効
        console.log(num2);
    }
    // ここでは変数num2は無効
    console.log(num2);
}
```

上記コードを実行すると先ほどと同じように`ReferenceError: num2 is not defined`というエラーが出ます。
これはif文のブロック内で宣言された変数をブロック外で使用しようとしたから発生するエラーになります。
では`let`キーワードの特徴についてある程度把握してきたところで、新しく`var`というキーワードについても紹介します。
先ほどのエラーになったコードを下記のように書き換えます。

```js
function myFunction(){
    let num = 1;
    if (num == 1) {
        var num2 = 2; // 変数num2はif文のブロック外でも有効
        console.log(num2);
    }
    // 変数num2は有効
    console.log(num2);
}
```

今度はエラーにならずに実行することができるようになります。
`var`というのは昔からあるJavaScriptの変数宣言時のキーワードで、letとは違い、宣言されたブロック外でも使用することが可能です。
しかし、ブロック外と言っても、関数のブロック外は例外です。
例えば下記のような場合は引き続きエラーになります。

```js
function myFunction(){
    var num = 1; // 変数numはmyFunction関数の中でのみ有効
    console.log(num);
    myFunction2();
}
function myFunction2(){
    // 変数numはmyFunction2の中では宣言されていないので、無効
    console.log(num);
}
```

上記コードを実行するには下記のように変更する必要があります。

```js
var num = 1; // 変数numはmyFunction,myFunction2関数の中で有効
function myFunction(){
    console.log(num);
    myFunction2();
}
function myFunction2(){
    console.log(num);
}
```

関数のブロック外で変数を宣言すると、複数の関数で共通で使用できる変数になります。
このような変数のことを`グローバル変数`と呼びます。
しかし`グローバル変数`は意図しない変数の書き換えなどを複数の関数間で共有してしまうことになり、プログラムの保守性が下がってしまうので、基本的には使用しない方が良いとされています。
また変数を宣言する際は実は`var`も`let`も省略することが可能なのですが、例えば下記のように変数を宣言すると、変数numは`グローバル変数`になります。

```js
function myFunction(){
    num = 1; // 変数numはグローバル変数
    console.log(num);
    myFunction2();
}
function myFunction2(){
    // 変数numはグローバル変数
    console.log(num);
}
```

意図せず`グローバル変数`になってしまわないよう、またなるべく`グローバル変数`を使用しないように、必ず`var`か`let`を使用して変数を宣言するようにしましょう。
また、近年では基本的に`let`を用いるのが望ましいとされていますので、なるべく`var`も使用しないようにしましょう。

## constについて

`var`、`let`キーワードについて調べると必ず`const`というキーワードについても列挙して解説されている記事が沢山ヒットします。
これら3つのキーワードについては頻繁に使用するので、`const`についても紹介していきます。
まず`const`というのは再代入、再宣言をすることを禁止することができるキーワードです。

```js
function myFunction(){
    var num1 = 1;
    num1 = 2; // varは再代入可能
    var num1 = 3; // varは再宣言可能

    let num2 = 1;
    num2 = 2; // letは再代入可能
    let num2 = 3; // letは再宣言不可能なので文法エラーになる

    const num3 = 1;
    num3 = 2; // constは再代入不可能なので実行時エラーになる
    const num3 = 3; // constは再宣言不可能なので文法エラーになる
}
```

上記のように3つのキーワードを使用して変数を宣言するとそれぞれ制限事項が異なります。
`const`は主に初期値を決めて、以降その初期値をプログラム内で誤って書き換えることがないように、また書き換えている場合はプログラムに意図しない処理が入りこんでしまっていることが分かるように実行時にエラーになります。
主な使用用途としては、外部APIを呼び出す際に必要になるAPIキーや、プログラムでエラー発生時にエラーを通知するメールアドレスなど、プログラム実行中に変更する必要の無い値を変数内に保存しておいて、プログラム内で使用する場面になります。
この辺もゆくゆく使用する場面が出てきますので、特徴だけ押さえておいてもらえれば良いと思います。

## 演習問題

(1). 下記のプログラムを実行すると事前に意図した表示とは異なって表示されるプログラムになってしまっていました。意図した表示になるようにプログラムを修正して下さい。
また修正する際にはなるべくグローバル変数を使用しないように配慮して修正して下さい。

```js
function myFunction(){
    num = 1;
    myFunction2();
    console.log("myFunction内でのnumは" + num + "です。");
}
function myFunction2(){
    num = num + 1;
    console.log("myFunction2内でのnumは" + num + "です。");
}
```

事前に期待していた実行結果

```
myFunction2内でのnumは2です。
myFunction内でのnumは1です。
```

現在のコード実行結果

```
myFunction2内でのnumは2です。
myFunction内でのnumは2です。
```

(2). 下記のプログラムを実行すると事前に意図した表示とは異なって表示されるプログラムになってしまっていました。意図した表示になるようにプログラムを修正して下さい。
また、仮に変数の値を書き換えられてしまっていた場合に実行時に書き換えられた際にエラーが発生するようにして下さい。

```js
function myFunction(){
    let name = "鈴木一郎";
    console.log(name + "の趣味はドライブです。");
    console.log(name + "の出身地は東京都です。");
    name = "山田太郎";
    console.log(name + "は現在東京の会社で働いています。");
}
```

事前に期待していた実行結果

```
鈴木一郎の趣味はドライブです。
鈴木一郎の出身地は東京都です。
鈴木一郎は現在東京の会社で働いています。
```

現在のコード実行結果

```
鈴木一郎の趣味はドライブです。
鈴木一郎の出身地は東京都です。
山田太郎は現在東京の会社で働いています。
```

## まとめ

いかがでしたでしょうか。
今回はずっとおまじないとして記載していた`let`についての紹介となりました。
変数の有効範囲は非常に重要な概念ですので、しっかりと理解しておきましょう。
それではまた次の記事でお会いしましょう。