どうも。つじけ(tsujikenzo)です。2020年11月から始まりましたノンプロ研GAS初級講座7期ですが、このシリーズでは講座中では時間の都合でお伝えできなかったことなどを、全6回+おまけという感じでお届けしております。本日は3回目でございます。
前回のおさらい
前回は「制御構文」ということで、if文やswitch文による条件分岐、for文やwhile文によるループ処理をお届けしました。
まずは正しい書き方に慣れるまでは反復して書くことを心がけましょう。脳に焼き付けるのです。実行しましょう。
“` while (!脳に焼き付いた) {一日一行GASを書いて脳の状態を変更する}; “`
DAY3補講
それではDAY3を振り返ります。今日は「関数」と「配列」についてでした。
関数
「関数」とか「Function」とか別の言語だと「プロシージャ」とか、処理そのものの名前だったり、処理の単位について使ったり言葉の使われ方は色々変わってくるので、厳密な定義や呼び方の議論はよそ様のブログなどにお願いしましょう。
大事なのは「何か情報を与えると何か処理をして何か返してくれる」というのが「関数」です。もう少し言うと「何か情報を与えると(与えなくてもいい)何か処理をして(処理しなくてもいい)何か返してくれる(返さなくてもいい)」というのが正しく、○○しなくてもという部分は省略されてるだけです。(VBAでは戻り値があるかどうかで関数を区別してます)
どっから関数って言うの
なので、下記A~Dは全て「関数:myFunction」ですが(functionから始まる宣言をされている為)、Cぐらいから所謂「関数」ぽくなるかもしれませんね。この辺の言葉遣いは非常に難しいんです。あまり気にしないでください。ただ私自身プログラミング学習を始めた時に「関数ってなんなの?」がずっと分からなかった経験があるのでご案内です💦
“` //A.定数nameを定義する関数 function myFunction(){
const name;
}
“`
“` //B.定数nameに’つじけ’を代入してログ出力する関数 function myFunction(){
const name = ‘つじけ’ console.log(name);
}
“`
“` //C.関数myFunctionに情報(値)を与えてnameに代入してログ出力する関数 function myFunction(x){
const name = x; console.log(name); }
“`
“` //D.関数myFunctionに情報(値)を与えてnameに代入して戻り値として得る関数 function myFunction(x){
const name = x; return name; }
“`
引数と仮引数
先ほど「何か情報(値)を与えると」と言いましたが、関数には値を渡すことができます。授業ではこのように説明しました。
引数と仮引数のことを英語で「paramater」「argument」 と言いますが、厳密にどっちがどっちという決着はつけません。引数も仮引数もどっちもパラメーターと言えるし、オーギュメントとも言えるからです。
ただ、一般的には
- 関数を呼び出す時に渡す値の事を実引数(じつひきすう)「パラメーター」
- 関数定義されて待ち構えてる引数を仮引数(かりひきすう)「オーギュメント」
と区別してる気もします。今後[param][arg]なんて変数名を見つけたら「つじけさんが言ってたやつや」と思ってくださいw
戻り値
関数の中にreturnを置くと、そこで処理が止まって、その時点でreturnに定義されてる値を返す仕組みになってます。
“` //E.myFunctionを実行して関数getName()に’つじけ’を渡すと’つじけ先生’に変換してくれる function myFunction(){ const value = getName(‘つじけ’); console.log(value); } function getName(x){
const name = x; return name + ‘先生’; }
“`
関数リテラル
難しそうだけど、難しくありません。講座では一つ一つの言葉をしっかり理解できるように説明しました。
2点だけ補足すると、関数リテラルを変数に代入した時は、変数名()で呼び出すことができます。今までこのように変数(name)は変数名(name)で呼び出していました。
“` function myFunction(){
const name = ‘つじけ’ console.log(name); }
“`
しかし、変数に関数が代入されることにより、変数()で呼び出すようになったのです。テキストではconst 関数名 =と書いてますね。
“` function myFunction(){
const name = (x) => { return x + ‘様’; }
const result = name(‘つじけ’); console.log(result); }
“`
もう一つは記述順です。呼び出し関数は関数定義の後に書かないとエラーになってしまいます。
アロー関数
アロー関数は便利なんですが、インデントが崩れるという致命的なデメリットもあります。(もうすぐ新しいGASエディタがリリースされるのでそれまで我慢💦)なので、できるだけアロー関数はワンライナーで書けるといいでしょう。以下はワンライナーで書くコツです。
{}とreturnを省略する
“` const getArea = (width, height) => width * height;
console.log(getArea(10,2));//20 “`
引数が一つの場合は()も省略する
“` const getExponent = number => number ** 4;
console.log(getExponent(2));//16 “`
引数がない場合は()が必要
“` const getHello = () => console.log(‘Hello GAS!’);
getHello();//’Hello GAS!’
“`
アロー関数が宣言された場所によってthisの挙動が変わりますが、ここでは割愛します。
配列
今後、GASで様々なデータを扱っていきますが、複数の要素を扱うのに便利なのが配列とオブジェクトです。
リテラル(型を認識してもらう為の書き方のルール)は、
配列・・・・・・角カッコ[]で囲って、中の値はカンマ区切り。1つ1つの値を要素と呼ぶ。
オブジェクト・・波カッコ{}で囲って、中の値はキーとバリューがコロン:でセットになっていてカンマ区切り。1つ1つの値をプロパティと呼ぶ。
です。コードを動かすのに必要なミニマムデータをリテラルに書けるように反復練習しましょう。慣れが大事です。
変数名のヒント
配列やオブジェクトを変数に代入する際は、複数系を使うなど、中にどんな値が代入されているのか読みやすい工夫を心掛けましょう。後程要素を取り出して変数に格納する際に便利です。
“` const members = [‘Bob’, ‘Tom’, John]; const values = [10,20,30]; const member = members[0]; const value = values[0]; “`
配列の型はobject
そんな配列とオブジェクトですが、実は配列型というデータ型があるわけではなく、配列はオブジェクト型です。typeof演算子で型を確認してみましょう。
“` const numbers = [10, 20, 30];
console.log(typeof numbers); //object “`
・Array型があるわけじゃない。
・実は配列もオブジェクト型で、実際の中身はインデックスをキー、要素をバリューとしたオブジェクトになってるから。
という訳です。
“` const numbers = [10, 20, 30];
//中身はindex:valueになっている→{0:10, 1:20, 3:30} “`
for of文でなぜconstが使えるのか
とりあえずfor of文にはconstが使えると覚えて頂いて問題ありません💦
なぜなのか?は中級以上の深い知識が必要になってくるのですが、for文もif文しかり(条件式)の判定によって、ブロックスコープ{}の中の処理をループしているとお伝えしました。(初期化式;やインクリメント演算子i++は省略してます)
“` //(条件式)がtrueであり続ける限り//処理を実行する for (条件式) { //処理 }
“`
しかしながら、for文(カウント変数型)とfor文(for of文)の挙動は少し異なります。
- for文(カウント変数型)・・カウント変数が条件式によってfalseを返すまで回す
- for文(for of文)・・・・・イテラブルオブジェクトを回してfalseを返すまで回す
“` //for文(カウント変数型) for (let i = 1; i<10; i++) { //iが1から始まって10になるまで{}の中の処理を回す }
“`
“` //for文(for of文) for (const イテラブルオブジェクトの1要素 of イテラブルオブジェクト) { //イテラブルオブジェクトから1要素を取り出して{}の処理を回す }
“`
つまり、カウント変数型はfor文がスタートとしてからループが終わるまで最初のブロックスコープ{}を保持しているの(※)に対し、for of文はループが終わるまでブロックスコープ{}を毎回生成しているという違いがあります。
(※誤りでした。カウント変数型も毎度ブロックスコープを生成しています。正しい理解をする為に別記事を書きました。)
訂正記事のURL
上達のコツはfor of文を作成する時に変数名を分かりやすく付けることです。意識してみてください。
“` for (const member of members) { //処理 }
for (const value of values) { //処理 }
for (const element of elements) { //処理 }
“`
カウント変数型とfor of文のfor文の使い分け
for of文は短くて読みやすいので便利ですが、カウント変数型のように配列のインデックスを操作(例えばインデックス1からループを始めるなど)する為には、配列.entries()メソッドを使う必要があります。(※entries()メソッドは中級で習います)
“` let numbers = [10,20,30]; for(const [index,number] of numbers.entries()){ if (index > 0 && index < 2) console.log(number); //20 } ```
この場合はカウント変数型の方が読みやすそうですね。
“` numbers = [10,20,30]; for(let i = 1; i< 2; i++){ console.log(numbers[i]); //20 } ```
for of文を習得するとfor ofで書くことが多くなっていくと思いますが、カウント変数型で書くかどうか迷ったら「配列のインデックスをループ処理の中で使いたいかどうか」というのを基準にしてみてください。
まとめ
以上で、DAY3の振り返りと補足でした。ちょっとずつ覚えることが増えてきて、補講的にも中級レベルの内容をついついご紹介してしまってますが、まずは講座のテキストの演習・課題を何度も解いてみて、『目慣れ・耳慣れ・タイプ慣れ』しましょう。もう何も見なくても書けるなってぐらいで「あれ?ここの型や書き方の順番を変えたらどうなるんだろ」とかミニマムテストをやってみると新しい気付きがあって腹落ち(なるほどね。分かった。)したりします。頑張りましょう!
次回は『オブジェクト』です。(いつスプレッドシートを触らせてくれるの?💦)お楽しみに!
【追記】
Slackの宿題添削より20201212
“` function myFunction(){ getHoge(); } function getHoge(){ console.log(‘hoge’); }
“`
と
“` function myFunction(){ console.log(getHoge()); } function getHoge(){ return ‘hoge’; } “`
って同じ出力結果が出ますよね これどっちが正解なの?って話なんですが、『関数とは戻り値を持つ』と考えた方が後々の学習にとって良い結果を生むと思います。何度も使うような処理は関数化(パーツ化)していきますし、メンテナンスしやすい方がいいです。
“` function getHoge(){ return ‘hoge’; } “`
と定義しておいた方が、console.log()でログ出力したり、関数からreturnさせた戻り値を変数に格納したりできます。
“` function myFunction(){ const hoge = getHoge(); } “`