Google Apps Scriptでの変数のスコープについて

GoogleAppsScript

Google Apps Script

Microsoft Officeを使わなくなってからもうどれだけ経つだろう・・・

とりあえずワードは元から使ってなかったが、Excelも最後に使ったのは2007年ぐらいか。
一番最後まで使ってたのはPowerPointだけど、それも2010年あたりまでだったような気がする。

その後、Open Officeやその派生版のLibre Officeを使ってて、いつからかは記憶にないが、ここ数年はGoogle Apps(で呼び方合ってるのかな)というよりはSpread Sheetを重用しています。

これまでは特に必要なかったから気にしなかったんだけど、最近Google Apps Script(GAS)ってのが気になってまして。
Lotusやエクセルでいうところのマクロってことかな?
とにかく、これを使いこなした方が後々役に立つんじゃなかろうか、という程度の認識のもと、少し弄ってみました。

んで、ネット上に転がってる入門編のサンプルスクリプトを写経したりいろいろ書き換えたりしてるうちに、妙なことに気がつきました。

Google Apps Script(GAS) はJavascript互換?

ちょっと今の所まだよくわかってないんですけれど、Javascriptで書いたら動くんじゃね?ということで合ってるんでしょうか・・・

こんな感じの記事がたくさんありますしおすし。
祝!Google Apps Scriptが「V8ランタイム」をサポート!モダンなECMAScript構文が使えるようになった

なにぶんワタクシ、元々JSはそんなに得意な方じゃない・・・というか、jQueryで済ませてたクチ(ライトボックスや画像スライダーをスクラッチで書く程度にはやってたけど)で、さらにブランクが長いので、本当にイチから入門するつもりでいろいろ遊んでたわけです。

ちなみに利用させていただいたのは上記と同じくこちらのサイト。すごいです。全24回分の記事があるし、説明も丁寧なので、プログラミング未経験者でも何とか理解を進めながら動くものを作れそうです。
【初心者向けGAS】本当の最初の一歩!スクリプトエディタでプロジェクトを開く

変数のスコープってこれでいいのだろうか?

で、ちょうどこんな感じで変数の宣言やらテンプレート文字列やらを弄ってた時、

function myFunction() {
  let x = 10, y = 5;
  console.log( `${x} + ${y} = ${x+y}` ); // 10 + 5 = 15
}

いろんなパターンで出力させようと思ったので、とりあえず関数にしますわな。

function myFunction() {
  function calc( x, y ) {
    console.log( `${x} + ${y} = ${x+y}` );
  }

  calc( 10, 7 ); // 10 + 7 = 17
  calc( 2.490876627891, 7 ); // 2.490876627891 + 7 = 9.490876627891
  calc( -100, 99 ); // -100 + 99 = -1
  calc( hoge, fuga ); //エラー ReferenceError: hoge is not defined
  // 文字列結合イケる??
  calc( "12345", "897652" ); // 12345 + 897652 = 12345897652
  calc( 100, "hoge" ); // 100 + hoge = 100hoge

}

まあ、型のキャストとかも含めてw、こんな感じでいろいろ見てみますわな。
で、ふと思ったわけです。const使えるようになったんだけど、関数外で宣言しても使えたりして。とか。

すると、

function myFunction() {
  const x = 100;

  function calc( y ) {

    console.log( `${x} + ${y} = ${x+y}` );
  }

calc(5); // 100 + 5 = 105

}

ほぉ〜〜〜、使えるんや??まじか・・・。

ほな、関数内で同名の変数使ったらどうなるんじゃろ?

function myFunction() {

 const x = 100;

  function calc( y ) {
    const x = 10;
    console.log( `${x} + ${y} = ${x+y}` );
  }

  calc(5); // 10 + 5 = 15

  console.log( x ); // 100

}

ほほぉ〜〜〜

ちなみにcalc関数内の宣言はconstでもletでもvarでも挙動は変わらず。当然ですが。

では、constではなくletで宣言して書き換え可能にして、関数内で書き換えてみましょう。

function myFunction() {

 let x = 100;

  function calc( y ) {
    x = 10;
    console.log( `${x} + ${y} = ${x+y}` );
  }

  calc(5); // 10 + 5 = 15

  console.log( x ); // 10

}

あれれれ〜〜、代入されちゃったよ。宣言したxはcalc関数内で書き換えられました。

じゃあ、これならどうだ??

function myFunction() {

 let x = 100;

  function calc( y ) {
    let x = 10; // 別に宣言してやった!!!
    console.log( `${x} + ${y} = ${x+y}` );
  }

  calc(5); // 10 + 5 = 15

  console.log( x ); // 100

}

calc関数内では別途宣言してxという変数を作った。
すると、関数外では書き換えられていない元のxの値が復活。

・・・ということは、これはエラーになるのか?

function myFunction() {

 const x = 100;

  function calc( y ) {
    x = 10;
    console.log( `${x} + ${y} = ${x+y}` );
  }

  calc(5); //エラー  TypeError: Assignment to constant variable.

}

だよね、良かった(笑

結局、この仕様は誰の仕様なのだ??

ということで、javascriptのスコープに関する知識に関しての私の未熟さ故ではありますが、

ちんぷんかんぷんです。

これがECMAScriptの仕様なのか、GAS独自の仕様なのか、調べてみないと分かりませんが・・・誰か知ってる人がいましたら教えてくだされば有難き幸せ。

とはいえ、おそらくGASではそんな大きなプログラムを組むことはないでしょうから、同名の変数を使う必要が出てくることもないだろうし、うっかりやってしまうこともないでしょう。なので、気にすることはないでしょうねぇ。多分。

多分。