どうも。つじけ(tsujikenzo)です。このシリーズでは、2021年5月から始まりました「ノンプロ研GAS中級講座5期」について、全8回でお届けします。今日は2回目のDay1です。
前回のおさらい
前回は、いよいよ講座が始まりますよ、ということで 「スケジュールと事前課題の確認」 をしました。
今日は、Day1で 「スコープと関数」 についてお届けします。
今日のアジェンダ
- スコープ
- 関数
スクリプトエディタの準備
講座では、スクリプトエディタの環境として、中級っぽいミニTipsをお伝えしました。
スクリプトファイルのフォルダ分け
スクリプトファイルはフォルダ分けすることができます。書き方のルールは以下です。
フォルダ名/スクリプトファイル名.gs
半角スラッシュ/の前後には、スペースを入れないことです。
※スクリプトファイルをフォルダに格納した場合は、スクリプトファイルの上下の移動ができなくなるので、管理者でファイルの移動をされたくない場合は利用価値が高まるかもしれません。
ダークモードの違い
スクリプトエディタには2種類のダークモードがあります。
デフォルトのダークモードは 「ハイコントラストテーマ」 と呼ばれています。
[F1] キーで コマンドパレット を開き、 「ハイ」 と日本語で検索して出てくる 「ハイコントラストテーマへの切り替え」 をクリックします。
このような見た目です。
一方、chromeには拡張機能 [AppsScript Color] があります。
スクリプトエディタにアイコンが表示されますので、クリックすると切り替わります。ハイコントラストテーマと少し見た目が異なりますね。
お好みのダークモードを選択しましょう。(型判定ができるため、私は白画面よりダークモードを推奨します。)
スコープ
スクリプトファイルの実行順
スクリプトファイルは、 スクリプトファイルメニューの上から順 に実行されます。試しに、[01.gs] ファイルを下に移動して、myFunction1_01を実行すると、 「ReferenceError: msg is not defined」 というエラーが出ます。
これは、[01_02.gs] に書かれている変数[msg]が、まだ定義されていないからです。
さらに、 演習1-01 では、console.logの呼び出し順について、以下のように確認できます。
1. 関数を実行した同スクリプトファイル内のグローバル領域
2. 同プロジェクト内の他のスクリプトファイル内のグローバル領域
3. 実行した関数内のローカル領域
ブレークポイント
ブレークポイントのショートカットキーは [Ctrl +B] です。
「変数宣言(var/let/const)とはなにか」 や 「Script Object」 については、次回の講座でお届けします。
スコープの歴史
もともとは、JavaScriptには、 グローバルスコープ と 関数スコープ しか存在しませんでした。ローカルスコープといえば、関数スコープのことでした。
そこに ES6 から ブロックスコープ が導入されたため、ローカルスコープは 「関数スコープ」 と 「ブロックスコープ」 の2種類となりました。
グローバル領域に書くコード
グローバル領域には、コードを書いてはいけないわけではありません。毎回実行されて問題のないもの、重複記述すると冗長なものをグローバル領域に置いたりします。
また、グローバル領域に書かれていることを明示する為に、 「アッパースネーク記法」 で書くようにしています。読んだときにわかりやすいのが一番です。
– UPPER_SNAKE_CASE
– lower_snake_case
– UpperCamelCase
– lowerCamelCase
–
const FOLDER_ID = 'フォルダID';
const SS_ID = 'スプレッドシートID';
function myFunction1() {
// FOLDER_IDを使った処理
// SS_IDを使った処理
}
function myFunction2() {
// FOLDER_IDを使った処理
// SS_IDを使った処理
}
この、 「グローバル領域に変数を置く」 という処理ですが、古代からプログラミングと切っても切れない関係です。 「グローバル変数」 について考察はとても奥が深いものになりますので、徐々になれていきましょう。
ここでは、下記2点のご紹介にとどめておきます。
一般にグローバル変数は、その非局在的な性質ゆえに、好ましくない実践だと考えられている。すなわち、グローバル変数は潜在的にどこかで変更される可能性があり、またプログラムの一部はそれに依存してしまう恐れがあるからである。グローバル変数はそれゆえ相互依存を生み出す無限の可能性を持っており、相互依存が高まることは複雑性を増大することにつながる。
しかしグローバル変数が適する状況もある。例えば、システム起動時に一度だけファイルから読み出し、以降は様々な関数を通して継続的によく使われるような設定情報を格納する変数を、関数に毎回引数として渡すことを避けるために使用できる。また、並列実行するスレッドやシグナルハンドラのように、呼び出し側/被呼び出し側の関係を持たないコード同士でセクション間情報を受け渡すためにも広く使われる。
過去に、 「スコープと名前」 について考察したことがありますので、こちらも参考にしていただければ幸いです。スコープという技術が用いられた大前提は 「変数名の衝突をどう回避するか」 です。
関数
文字列の分割を行うのは、Stringクラスの split()メソッド です。
構文は以下のようになっていて、区切り文字が現れるたびに、分割した文字列を 配列 で返します。第2引数の 分割数 は省略できますが、指定されると分割数に達すると 停止 します。
str.split(区切り文字・正規表現, 分割数);
参照渡しと値渡し
講座では、 「関数の引数のやりとりにおける参照渡しと値渡し」 をご紹介しましたが、もうちょっと理解したいという方の為に、 「変数に代入するときの型の違い」 を用いてご説明します。
関数のときと同じように、参照渡しと値渡しの要となるのは 「データ型」 です。以下のコードを実行してみましょう。
//プリミティブ型
function byVal(){
let x, y;
y = x;
x = 100;
console.log(y); //10
}
//オブジェクト
function byRef(){
let arr, arr2;
arr = ['hoge'];
arr2 = arr;
arr.push('fuga');
console.log(arr2); //['hoge', 'fuga']
}
なぜこのような挙動になるのかは、講座内でお伝えしました。メモリアドレスの参照先に 値 が割り当てられているのか、配列のような、 参照先 が割り当てられているのか、の違いです。
関数のパーツ化、サブ化
超初級から学びはじめた私の経験のお話をすると、初級と中級講座の間ぐらいに 「関数化のコツを知りたい」 と思うようになります。
「この書き方でいいのだろうか」 、 「もっといい書き方があるのでは」 という悩みです。しかしながらこれらの悩みはほぼ取り越し苦労で、初級講座を終えた段階では大規模なソフトウェア開発をすることは稀だと思います。
今はたくさん書いて、たくさんエラーと向き合って、思った通りに動くツールを量産するといいと思います。やがて、似たような処理をよく書くことに気付き、 「同じ処理は1つにまとめよう」 とか 「可変部分を引数として渡して、共通処理を関数化しよう」 というアイディアが生まれます。
もっとも大切なことは 「読みやすいコードを書くこと」 です。 「リーダブルコード」 という考え方です。中級以降の必須スキルですので、こちらの書籍は一読をおススメします。
まとめ
以上で、 「スコープと関数」 をお届けしました。講座に入る前に、スクリプトエディタのちょっとしたTipsをご紹介しました。
スコープ・関数 ともに、まだまだ語り切れない補足がありますが、今回は必要最低限なものだけをチョイスしました。
プログラミング学習は深掘りするとキリがありません。あくまで自分やチームメンバーがコーディングしやすくなるようなスキルを磨いて、業務効率化 に直結するツール作りを意識していただければ幸いです。
次回は、 「クラス・ライブラリ」 をお届けします。
このシリーズの目次
- [ノンプロ研]GAS中級講座5期 事前課題
- [ノンプロ研]GAS中級講座5期Day1 スコープと関数
- [ノンプロ研]GAS中級講座5期Day2 クラス・ライブラリ
- [ノンプロ研]GAS中級講座5期Day3 組み込みオブジェクト
- [ノンプロ研]GAS中級講座5期Day4 ScriptServices1
- [ノンプロ研]GAS中級講座5期Day5 ScriptServices2
- [ノンプロ研]GAS中級講座5期Day6 HTTP通信・API
- [ノンプロ研]GAS中級講座5期卒業LT ノンプログラマーによるGAS開発モデルとは
- [ノンプロ研]GAS中級講座5期卒業LT プロの開発を知ろう
- [ノンプロ研]GAS中級講座5期卒業LT ノンプログラマーによる開発