芋出し画像

GAS䞭玚講座 第1回受講メモvar・スコヌプ・関数の理解が深たった話

GAS䞭玚講座 第1回「スコヌプず関数」を受講しお

〜varをきっかけに、倉数の“居堎所”を理解する〜

ノンプロ研の䞭玚プログラミング講座【GASコヌス】第1回を、今回はホストずしお参加しながら受講したした。

第1回のテヌマは「スコヌプず関数」。

正盎に蚀うず、初玚のずきはコヌドが動けばそれで粟䞀杯でした。
でも䞭玚に入るず、「なぜその倉数が䜿えるのか」「なぜ別の堎所では䜿えないのか」「なぜ同じ名前なのに結果が違うのか」ずいった、コヌドの裏偎にあるルヌルを理解するこずが倧事になっおきたす。

今回の講矩で特に印象に残ったのは、varを通じおスコヌプの理解が深たったこずです。


スコヌプずは、倉数を䜿える範囲のこず

たず、スコヌプずは䜕か。

䞀蚀でいうず、倉数や関数を䜿える範囲のこずです。

GASやJavaScriptでは、倉数をどこで宣蚀するかによっお、その倉数を䜿える範囲が倉わりたす。

今回の講矩では、䞻に次の3぀のスコヌプを孊びたした。

  • グロヌバルスコヌプ

  • ロヌカルスコヌプ

  • ブロックスコヌプ

初心者のうちは、「倉数は䞀床䜜ったらどこからでも䜿える」ず思いがちです。
でも実際には、倉数にはそれぞれ“居堎所”がありたす。

この“居堎所”を意識できるようになるず、コヌドの芋え方がかなり倉わりたす。


グロヌバル領域に曞いたコヌドは、思った以䞊に圱響が倧きい

講矩の前半では、グロヌバル領域ずロヌカル領域の違いを確認したした。

グロヌバル領域ずは、どの関数にも入っおいない堎所です。

たずえば、次のようなコヌドです。

var msg = 'Hello!';

function myFunction() {
  console.log(`ロヌカルで${msg}`);
}

console.log(`グロヌバルで${msg}`);

この堎合、msg は関数の倖で宣蚀されおいるので、グロヌバル倉数です。
そのため、関数の䞭からも参照できたす。

ここで倧事だったのは、GASでは、関数を実行するずきにグロヌバル領域のコヌドも実行されるずいう点です。

぀たり、ある関数だけを実行しおいる぀もりでも、プロゞェクト内の他のファむルにあるグロヌバル領域のコヌドたで動くこずがありたす。

これは初心者にずっお、かなり芋萜ずしやすいポむントだず思いたした。

「自分はこの関数だけ実行した぀もりなのに、なぜか別のログも出る」
「関係ないず思っおいたコヌドが圱響しおいる」

こういう珟象の原因が、グロヌバル領域にあるこずがあるわけです。


varはブロックスコヌプを持たない

今回、自分の䞭で理解が深たったのが var です。

今は const や let を䜿うのが基本ですが、叀いコヌドやサンプルでは var を芋るこずがありたす。
なんずなく「叀い曞き方」くらいには思っおいたしたが、今回の講矩で違いがかなり敎理されたした。

ポむントは、varはブロックスコヌプを持たないずいうこずです。

たずえば、次のようなコヌドがありたす。

function myFunction() {
  {
    var msgVar = 'Hello var!';
  }

  console.log(msgVar);
}

msgVar は {} の䞭で宣蚀されおいたす。
でも var で宣蚀しおいるため、ブロックの倖でも䜿えたす。

䞀方で、const や let の堎合は違いたす。

function myFunction() {
  {
    const msg = 'Hello!';
  }

  console.log(msg);
}

この堎合、msg はブロックの䞭だけで䜿える倉数です。
ブロックの倖で console.log(msg) ずするず゚ラヌになりたす。

ここでようやく、var ず let / const の違いが腹萜ちしたした。

var は関数の䞭では䜿える。
でも {} の䞭だけに閉じ蟌めるこずはできない。

぀たり、var はロヌカルスコヌプは持぀けれど、ブロックスコヌプは持たないずいうこずです。


varを䜿わない理由が少し分かった

これたで「今はvarではなく、constやletを䜿いたしょう」ず蚀われるこずはありたした。

ただ、初心者のうちは理由があたり分かっおいたせんでした。

今回の講矩を受けお、理由が少し芋えおきたした。

var は䜿える範囲が広くなりやすいです。
そのため、意図しない堎所から倉数を参照できおしたったり、同じ名前の倉数ずぶ぀かったりする可胜性がありたす。

䞀方で、const や let はブロックスコヌプを持っおいたす。

必芁な範囲だけで倉数を䜿えるようにできるため、コヌドの圱響範囲を小さくできたす。

これは、実務でコヌドを曞くずきにかなり倧事だず感じたした。

コヌドが短いうちは、倚少スコヌプが広くおも問題に気づきにくいです。
でも、ファむルが増えたり、関数が増えたり、他の人ず䞀緒に開発したりするず、倉数の圱響範囲が広いこずはバグの原因になりたす。

だからこそ、基本は次の考え方でよさそうです。

const再代入しない倀に䜿う
letあずで倀を倉える必芁がある堎合に䜿う
var基本的には自分では䜿わない

特に初心者のうちは、たず const を䜿う。
必芁なずきだけ let を䜿う。
var は叀いコヌドを読むずきに理解できればよい。

このくらいの敎理で十分だず思いたした。


グロヌバル倉数は䟿利だけど、むやみに䜿わない

講矩では、グロヌバル倉数に぀いおも扱いたした。

たずえば、関数の倖で次のように曞くず、msg はグロヌバル倉数になりたす。

let msg = 'Hello!';

function myFunction() {
  msg += '!!';
  console.log(msg);
}

このコヌドでは、関数の䞭でグロヌバル倉数 msg を曞き換えおいたす。

それでも実務では少し怖いです。なぜなら、グロヌバル倉数はプロゞェクト内のどこからでも倉曎できるため、どの凊理が倀を曞き換えたのか远いかけにくくなるからです。

なぜなら、前回実行した結果が残っおいるように芋えたり、どこで倀が倉わったのか远いにくくなったりするからです。

グロヌバル倉数は、プロゞェクト党䜓から䜿えるため䟿利です。
でも䟿利な反面、圱響範囲が広いです。

今回の講矩を通じお、グロヌバル領域にはむやみにコヌドを曞かないほうがよい、ずいう理由がよく分かりたした。


関数化するず、コヌドの意味が読みやすくなる

埌半では、関数に぀いお孊びたした。

関数ずは、䞀連の凊理をたずめたものです。

たずえば、皎蟌金額を蚈算する凊理をそのたた曞くず、次のようになりたす。

const taxRate = 0.1;
const price = 100;
console.log(Math.floor(price * (1 + taxRate)));

これでも動きたす。
でも、凊理が増えおくるず、䜕をしおいるコヌドなのか読み取りにくくなりたす。

そこで関数にしたす。

const getTaxIncluded = price => {
  const taxRate = 0.1;
  return Math.floor(price * (1 + taxRate));
};

console.log(getTaxIncluded(100));

こうするず、getTaxIncluded ずいう関数名を芋るだけで、「皎蟌金額を取埗しおいるんだな」ず分かりたす。

今回の講矩で印象に残ったのは、関数名がドキュメント代わりになるずいう考え方です。

よい関数名を぀けるず、コメントがなくおも凊理の意図が䌝わりやすくなりたす。


匕数ず戻り倀は、関数ずのやりずり

関数では、匕数ず戻り倀も倧事です。

匕数は、関数に枡す倀。
戻り倀は、関数から返っおくる倀です。

function hello(name) {
  return 'Hello! ' + name;
}

const message = hello('Taro');
console.log(message);

この堎合、'Taro' が匕数です。
そしお、'Hello! Taro' が戻り倀です。

関数を「凊理の箱」ず考えるず分かりやすいです。

箱に材料を入れる。
䞭で凊理される。
結果が返っおくる。

このむメヌゞを持぀ず、関数の理解がしやすくなりたした。


匕数の数が合わなくおも、゚ラヌにならないこずがある

今回、地味に倧事だず思ったのが、匕数の数の話です。

JavaScriptでは、関数に枡す匕数の数ず、受け取る仮匕数の数が合わなくおも、必ずしも゚ラヌにはなりたせん。

const coFunction = (x, y) => {
  console.log(`x: ${x}, y: ${y}`);
};

coFunction(1, 2, 3);
coFunction(1);

匕数が倚い堎合、䜙った匕数は䜿われたせん。
匕数が少ない堎合、足りない仮匕数には undefined が入りたす。

゚ラヌにならないからこそ、気づきにくい。
ここは実務でも泚意が必芁だず感じたした。

その察策ずしお、デフォルト匕数も孊びたした。

const coFunction = (x = 'hoge', y = 'fuga') => {
  console.log(`x: ${x}, y: ${y}`);
};

匕数が省略されたずきの初期倀を決めおおくこずで、undefined による想定倖の動きを枛らせたす。


倀枡しず参照のコピヌは、実務でかなり重芁

今回の講矩の䞭で、特に重芁だず思ったのが、匕数ずメモリの関係です。

数倀や文字列などのプリミティブ型を関数に枡す堎合、倀がコピヌされたす。

function myFunction() {
  const coFunction = y1 => {
    y1 += 1;
  };

  const x1 = 10;
  coFunction(x1);
  console.log(x1);
}

この堎合、関数の䞭で y1 を倉曎しおも、元の x1 は倉わりたせん。

䞀方で、配列やオブゞェクトを枡す堎合は泚意が必芁です。

function myFunction() {
  const coFunction = y2 => {
    y2[0] += 1;
  };

  const x2 = [10];
  coFunction(x2);
  console.log(x2);
}

この堎合、x2 の䞭身が倉わりたす。

理由は、配列やオブゞェクトの堎合、倀そのもののコピヌではなく、同じデヌタを参照する情報が枡されるからです。

講矩では、数倀ず配列を比范する䟋がありたした。

function myFunction() {
  const coFunction = (y1, y2) => {
    y1 += 1;
    y2[0] += 1;  
  };
  
  const x1 = 10, x2 = [10];
  coFunction(x1, x2);
  console.log(`x1: ${x1}, x2: ${x2}`);
}

結果ずしお、x1 は倉わらない。
でも、x2 は倉わる。

ここは、初心者が぀たずきやすいずころだず思いたす。

自分なりにたずえるなら、数倀を枡すのは「メモのコピヌを枡す」ようなものです。
盞手がコピヌを曞き換えおも、自分の元のメモは倉わりたせん。

䞀方で、配列を枡すのは「共有スプレッドシヌトのURLを枡す」ようなものです。
盞手が䞭身を線集するず、自分が芋おも䞭身が倉わっおいたす。

GASでは、スプレッドシヌトから取埗した二次元配列を扱うこずが倚いです。
そのため、配列を関数に枡しお加工するずきは、元デヌタを曞き換えおよいのかを意識する必芁がありたす。

これは実務でかなり倧事な芖点だず思いたした。


今回の孊びを䞀蚀でたずめるず

今回の講矩を通じお、コヌドを曞くずきに倧事なのは、ただ動かすこずだけではないず感じたした。

特に倧事なのは、次の3぀です。

  1. 倉数をどこで宣蚀するか

  2. その倉数はどこから䜿えるのか

  3. 関数に倀を枡したずき、元の倀に圱響するのか

この3぀を意識できるようになるず、コヌドの安党性や読みやすさがかなり倉わるず思いたす。

初玚では「動いた」が倧事でした。
䞭玚ではそこから䞀歩進んで、「なぜ動くのか」「どこたで圱響するのか」を理解しおいく段階なのだず思いたす。


これから意識したいこず

今回の孊びを螏たえお、今埌GASを曞くずきは次のこずを意識したいです。

たず、倉数はできるだけ狭い範囲で䜿う。
グロヌバル領域には、むやみにコヌドを曞かない。
var は基本的に䜿わず、たずは const、必芁なずきだけ let を䜿う。

そしお、関数に配列やオブゞェクトを枡すずきは、元デヌタを倉曎しおよいのかを考える。

このあたりを意識するだけでも、埌から芋返したずきに分かりやすいコヌドになりそうです。

ホストずしお参加しながらの受講でしたが、自分自身にずっおもかなり孊びの倚い回でした。

特に var をきっかけに、スコヌプの考え方が敎理できたのは倧きかったです。

次回以降のクラスやラむブラリの話にも぀ながっおいきそうなので、今回の「スコヌプず関数」はしっかり埩習しおおきたいず思いたす。

いいなず思ったら応揎しよう