はじめまして,駆け出しエンジニアのSawaDと申します。
異業種からエンジニアに転身したばかりです。毎日頑張っています🐘
最近実務でよく書いているJavaScriptについて,書いてみたいと思います。
突然ですが,次のコードをご覧下さい。
// hello.js
function main(){
const name = "山田";
const message = ((name) => {
return `こんにちは、${name}さん!`;
})(name);
console.log(message);
}
// 実行
main();
/* 実行結果
こんにちは、山田さん!
*/
実行結果にある通り,このコードは想定どおりに動きます。
が,初学者の方にはやや不思議に思われるのではないでしょうか。
少なくとも,1年前の私はこれを見ても全く意味がわからず,考えるのをやめるレベルでした😇
もちろん,こんな単純な処理をわざわざこんなコーディングで記述する必要は全くありませんね。
しかし,JavaScriptはこのような,学び始めに習うものとは全くと言ってよいほど異なる関数定義の方法をサポートしています。
ということは,このやり方には何かしらのメリットがある,ということなのでしょう🤔
今回は,駆け出しの私が,やっとそのメリットに少しだけ気づくことができたということを記念して(?)記事を書いてみたいと思います。
勉強し始めた頃を思い出しながら,基本的なところから丁寧に整理していきます。
少し長くなりそうですが,よろしければお付き合い下さい🙏
その名を即時関数という
先ほどのコードには,即時関数または即時実行関数と呼ばれる関数定義のしかたが含まれています。
略してIIFE(Immediately Invoked Function Expression)とも言うんだとか。
次の部分ですね。
const message = ((name) => {
return `こんにちは、${name}さん!`;
})(name);
「とりあえず変数name
を埋め込んだ文をmessage
に代入しているんだろう」
ということは何となく分かるのではないでしょうか。
また名前からも察しがつくと思いますが,ここでは文を返す関数が定義されその場で「即時」に実行されています。
message =
の次のカッコから3行目の})
までが,関数定義部分です。
へ〜そうなんだ〜
多分こういう感想になります🙂
これではメリットが感じられないですよね。だって習ったのと全然違うし🤔
ということで今回は,もう少し具体的な例で考えてみたいと思います。
個人的な結論として,この即時関数は,「ちょっとした」処理を記述する際のベストプラクティスとなりうる記法だと考えています。
今回のお題
次の処理の実装を想定してみます。
- 実行当日の日付を取得する
- その日付から, yyyy/mm/dd の年月日コードを取得する
- 同じ日付から,「年度」(4月始まり)を算出し "○○年度"の文字列を取得する
-
main()
の中でこれら2つを出力する。
最終完成形
先に,例の即時関数を使った最終形態を提示しておきます。
// finally.js
function main(){
// システム日付から当日を取得
const today = new Date();
// フォーマット済み年月日を取得
const formattedDate = ((date) => {
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}/${month}/${day}`; // yyyy/mm/dd形式の文字列にする
})(today);
// 年度を取得
const fiscalYear = ((date) => {
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月は0から始まるため+1
return month <= 3 ? `${(year - 1)}年度` : `${year}年度`; // 三項演算子で分岐処理
})(today);
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
// 実行
main();
/* 実行結果
今日は2024/10/03です。
年度は2024年度です。
*/
ちゃんと動いていますね。
(テンプレートリテラルや三項演算子の解説は今回は割愛します。)
では,これを本日のゴール🏁と据えまして,もっと基本的な書き方からみていきましょう。
基本のキ
おそらく,最初に習う関数定義のやり方は次のようなものでしょう。
// basic.js
function main(){
// システム日付から当日を取得
const today = new Date();
const formattedDate = getFormattedDate(today);
const fiscalYear = getFiscalYear(today);
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
// フォーマット済み年月日を取得する関数
function getFormattedDate(date){
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}/${month}/${day}`;
}
// 年度を取得する関数
function getFiscalYear(date){
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月は0から始まるため+1
return month <= 3 ? `${(year - 1)}年度` : `${year}年度`;
}
// 実行
main();
/* 実行結果
今日は2024/10/03です。
年度は2024年度です。
*/
個人的には, 特段問題がなければこれで全くOK だと思います👍
getFormattedDate()
といった関数名から,コメントを書かなくとも何をやりたいのかはだいたい想像がつきますし,何より,main()
がスッキリしていてGoodですね。
いきなり記事タイトルと矛盾するようですが,読みやすければ別になんだっていいんですよね😌
しかし, ハッキリNGと言える例,特にチームで開発する上ではまずやってはいけない例がいくつかあります。
初学者向けの記事としていますので,簡単に2つ紹介しておきます。
NG例1
変数を乱立させるベタ書き
// NG例1
function main(){
// システム日付から当日を取得
const today = new Date();
const yearForFormat = String(today.getFullYear());
const monthForFormat = String(today.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const dayForFormat = String(today.getDate()).padStart(2, '0');
// フォーマット済み年月日の作成
const formattedDate = `${yearForFormat}/${monthForFormat}/${dayForFormat}`;
const yearForFiscal = today.getFullYear();
const monthForFiscal = today.getMonth() + 1; // 月は0から始まるため+1
// 年度の作成
const fiscalYear = monthForFiscal <= 3 ? `${(yearForFiscal - 1)}年度` : `${yearForFiscal}年度`;
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
// 実行
main();
/* 実行結果
今日は2024/10/03です。
年度は2024年度です。
*/
いったいいくつの変数を把握しないといけないんでしょうか🙄
yearForFormat
とyearForFiscal
は,ほとんど同じなのでは?
しかし,これをどちらもyear
に揃えるとエラーになります。
// エラー例1
function main(){
// システム日付から当日を取得
const today = new Date();
const year = String(today.getFullYear());
const month = String(today.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(today.getDate()).padStart(2, '0');
const formattedDate = `${year}/${month}/${day}`;
const year = today.getFullYear();
const month = today.getMonth() + 1; // 月は0から始まるため+1
const fiscalYear = month <= 3 ? `${(year - 1)}年度` : `${year}年度`;
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
// 実行
main();
/* 実行結果
$ node exampleError1.js
/Users/sawad/dev/labo/IIFE_lesson/exampleError1.js:10
const year = today.getFullYear();
^
SyntaxError: Identifier 'year' has already been declared
*/
const
の仕様によるエラーです。year
を2度宣言しようとして,構文エラーになっています。
正確には「定数」であるconst
は再宣言が禁止されますから,何とか違う名前をつけようとして「本質的には同じなのに微妙に名前の違う変数」が乱立する訳ですね🌳🌳🌳
そして,これを力技で解決しようとしたものが次のNG例になります。
NG例2
let
なら怒られないんじゃないか?
// NG例2
function main(){
// システム日付から当日を取得
const today = new Date();
// letで宣言
let year = String(today.getFullYear());
let month = String(today.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
let day = String(today.getDate()).padStart(2, '0');
// フォーマット済み年月日の作成
const formattedDate = `${year}/${month}/${day}`;
// letなので再代入は可
year = today.getFullYear();
month = today.getMonth() + 1; // 月は0から始まるため+1
// 年度の作成
const fiscalYear = month <= 3 ? `${(year - 1)}年度` : `${year}年度`;
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
// 実行
main();
/* 実行結果
今日は2024/10/03です。
年度は2024年度です。
*/
はい,確かに結果はOKです。
ですが,途中でyear
やmonth
の「箱の中身が入れ替わる」処理となっているため,どこで入れ替わったのかを把握しておく必要が新たに生じてしまっています。これもアンチパターンです。
私も当初,const
はよく怒られる😡 let
は比較的優しい☺️ みたいな認識でした。
怒られるのはやだからとりあえずlet
使っとけ〜 と思っていました🙄
が,やはり実務で使うレベルを目指すのであれば,次は意識していくべきだと思って私は日々取り組んでいます。
- 変数(定数)の宣言は基本的に
const
が正解。const
で良くなるようなコーディングを目指すべき。 -
let
とconst
の使い分けは,プログラマー同士(あるいは未来の自分と)のコミュニケーションの一環である。 -
var
はダメ,ゼッタイ。
さすがに脱線が過ぎてしまうので詳細は割愛しますが,特に2点目のlet
とconst
の使い分けは,意識できるようになると一気に「初心者っぽくなくなる」気がしています🤔
上記2つのNG例に共通する問題点は,プログラム処理の最大の利点とも言える 「処理を切り出す」メリットを地面にぶん投げていること です。
逆に言えば,そのメリットを活かし,処理を切り出してそれぞれ別の場所に「閉じ込める」 ことによって,同じ名前の定数year
やmonth
を宣言してもお互い関与せず,問題が生じなくなるという訳です。
改めて「基本のキ」を分析してみると,それぞれの関数の中で定数名は,year
やmonth
のようにシンプルで直感的なものにおさまっています。
// フォーマット済み年月日を取得する関数
function getFormattedDate(date){
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}/${month}/${day}`;
}
// 年度を取得する関数
function getFiscalYear(date){
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月は0から始まるため+1
return month <= 3 ? `${(year - 1)}年度` : `${year}年度`;
}
変数名をできるだけ直感的に。
そしてこれを守るためには,処理の関数への切り出しを効率的に行えるほうがよい。
この命題を強調した上で,話を最初に戻します。
「基本のキ」が問題になる時
さて,実際に開発をやってみると,全体の処理を統べるようなmain
関数は,つい長くなってしまうものです。
// basic.js
function main(){
// システム日付から当日を取得
const today = new Date();
const formattedDate = getFormattedDate(today);
const fiscalYear = getFiscalYear(today);
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
/*
め
っ
ち
ゃ
な
が
い
処
理
*/
// フォーマット済み年月日を取得する関数
function getFormattedDate(date){
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}/${month}/${day}`;
}
// 年度を取得する関数
function getFiscalYear(date){
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月は0から始まるため+1
return month <= 3 ? `${(year - 1)}年度` : `${year}年度`;
}
// 実行
main();
/* 実行結果
今日は2024/10/03です。
年度は2024年度です。
*/
一度でも開発をやってみたことのある方からの「わかる〜〜🤣🤣」の声が聞きたいところ。
いや,本当にあるあるだと思うんですよね。
また,main()
が長くなってしまうことに関しては,特にプロトタイプ開発では一定仕方がないと思うんですよ。「美しいこと」<「動くこと」の段階って絶対にあると思いますし。
しかし何とも,スクロールであっちこっち移動して,目が疲れちゃうのはスマートじゃないですね🙄
もちろん,これを別ファイルに分けた場合も同様で,「処理の中身どうだったっけな」となった未来のあなたも,プロジェクトに参加したての同僚も,まずはファイルと関数を探して位置関係を把握するところから始まる訳です。
最初にも言及した通り,今回のお題は 「ちょっとした」処理 の代表例を想定しています。
「1行で書けるほど短くはないが,わざわざ別の場所に分けて書くほどでもない」処理というイメージです
(「ちょっとした」という日本語は不思議なもので,「ちょっとしたお土産」と,「ちょっとした有名人」は意味が全然違いますよね。。。なんだこの言語は🙄)
もし,これらの処理が,プロジェクト内で何度も利用される想定であれば,「基本のキ」のようにmain()
の外に別の関数として記述するのが再利用性があって良いと思います。
しかし,特に 「1回きり」 の処理の場合,それだけのためにコードが 「散!!🥷」 するのは,あまり直感的ではありません。
「関数式」を使う
ここで,次のような書き方が効果を発揮してきます。
// funcExpression.js
function main(){
// フォーマット済み年月日を取得する関数
const getFormattedDate = function(date){
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}/${month}/${day}`;
};
// 年度を取得する関数
const getFiscalYear = function(date){
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月は0から始まるため+1
return month <= 3 ? `${(year - 1)}年度` : `${year}年度`;
};
// システム日付から当日を取得
const today = new Date();
// todayを与えてそれぞれの関数を実行
const formattedDate = getFormattedDate(today);
const fiscalYear = getFiscalYear(today);
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
// 実行
main();
/* 実行結果
今日は2024/10/03です。
年度は2024年度です。
*/
「基本のキ」との大きな違いとして,まず全体レベルでは関数がmain()
だけになりました。上から下に読むことができるようになり,処理にまとまりが感じられますね👍
そして,年月コードの取得と年度の取得は別々の関数に切り出されているので,それぞれの中でyear
やmonth
といった直感的な変数名を使うことができています。
どちらもmain()
の中にありますが,それぞれの処理が関数に 「閉じ込められている」 ため,const
で宣言して全く問題ないわけです。
また,関数の定義のしかたが,実は大きく違っています。
難しい言葉を使えば 「関数宣言」 か 「関数式」 か,ということになりますが,名前は一旦さておき,形で比べてみて下さい。
// 関数宣言
function hello1(name) {
console.log(`こんにちは${name}さん!`);
}
hello1("山田");
// 関数式
const hello2 = function(name) {
console.log(`こんにちは${name}さん!`);
}
hello2("田中");
/* 実行結果
こんにちは山田さん!
こんにちは田中さん!
*/
まず大事なことは,「結果としてこの2つは全く同じ挙動である」 ということです。
その上で,この2つの何が異なっているかは,言葉で表現するとしっくり来ます。
-
まず
hello1()
のほうですが,これは「hello1
という名前の関数を宣言している。」ことになります。 -
次に
hello2
のほうですが,実はこれは, 「hello2
という定数(箱)に,名前の無い関数を格納している。」 という説明が当てはまります。
変数や定数の「箱」にはおよそ何でも格納することができるので,「関数」を入れることも可能です。
そして,関数を入れた箱は, hello2()
のように,()
をつけてあげることで,中に入っている関数をそのまま実行できる仕様になっています。
(今回は引数name
が必要なので,カッコの中に記述しています。)
結果的に同じように見える,のはこの仕様のためなんですね。
さて,この仕様と同様に理解の"コツ"となってくるのが,箱にしまっている関数それ自体は 「名前の無い関数」 である,ということです。
コードをよく見ればわかります。
1つ目がfunction hello1(name){〜}
と, function
の直後でhello1
という命名をしていたのに対して,2つ目の方はfunction
の後ろにいきなり引数の設定部分(name)
がきていますね。
// 関数式
const hello2 = function(name) {
console.log(`こんにちは${name}さん!`);
}
つまり, =
の右辺全体が「名無し関数」であり,「名前がつけられなければ後から呼び出す術がなくなってしまう」 ということで,左辺のhello2
という箱にしまっている,ということになる訳なんですね。
アロー関数に挑戦だ🏹
さて,本日のゴールに近づけて参りましょう。
この 「名無し関数」 の宣言は,次のように書き換えることができます。
// arrowHello.js
const hello2 = ((name) => {
console.log(`こんにちは、${name}さん!`);
})
// 実行
hello2("田中");
/* 実行結果
こんにちは田中さん!
*/
// 比較用。全く同じ処理。
const hello2 = function(name) {
console.log(`こんにちは${name}さん!`);
}
こちらが,よく「アロー関数」と呼ばれる記法になります。
=>
部分がまさに矢印,アローであることから呼ばれます。
この記法は慣れると直感的に理解しやすく,様々な場面で活用されています。
初学者の方は,ぜひ早めに慣れておくとよいと思います。
アロー記法には,様々な省略形があります。今回は割愛しますので,興味があれば調べてみて下さい。
このアロー記法を使って2つの関数を定義すると,次のようになります。
// アロー記法を使った変形
const getFormattedDate = ((date) => {
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}/${month}/${day}`;
});
const getFiscalYear = ((date) => {
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月は0から始まるため+1
return month <= 3 ? `${(year - 1)}年度` : `${year}年度`;
});
console.log(typeof getFormattedDate); // 実行結果: function
console.log(typeof getFiscalYear); // 実行結果: function
あまり理屈で考えずに,見て慣れるのが一番です👀
特に,return
があるのでつい, 変数に文字列が代入されているように見えてしまいますが,getFormattedDate
やgetFiscalYear
には関数が代入されている ,ということを意識するのがコツだと思います。
例のように typeof
で変数の型を調べてみるのは,よい勉強になるのでオススメです👍
私も最初は苦戦しましたが, (() => { 〜処理〜 })
この形が出てきたら関数なんだ,と「型」で覚えるようにして,少しずつ読めるようになっていきました。
(改めて)即時関数の登場
さて,いよいよ最終段階です。
ここまでの復習を兼ねて,次のmain()
を実行するとどうなりますか? 考えてみて下さい。
function main(){
(() => {
console.log("hello, world!")
});
}
//実行すると?
main()
はい。正解は「何も出力されない」ですね。 (すいません)
"hello world!"
を出力する 「名無し関数」 が書かれていますが,代入も実行もされていませんから,置かれているだけで無意味な状態です。
しかし次のようにすると...?
// IIFE_example.js
function main(){
(() => {
console.log("hello, world!")
})();
}
// 実行すると?
main();
/* 実行結果
hello world!
*/
お気づきでしょうか。
サイ○リヤ級の間違い探しのようですが, 「名無し関数」 の末尾に, ()
がくっついたことによって,関数が「実行された」のです!
function main(){
(() => {
console.log("hello, world!")
})(); // ←ココダヨ
}
やっと再登場できました👏
これが,即時関数 の仕様になります。
「名無し関数」の直後に()
をつけることによって,その場で実行させることができるのです。
引数のある関数の場合,この末尾のカッコに投入することになります。
// IIFE_example2.js
function main(){
const user = "鈴木";
((name) => {
console.log(`こんにちは、${name}さん!`);
})(user);
}
// 実行
main();
/* 実行結果
こんにちは、鈴木さん!
*/
次は関数の中でreturn
し,処理結果を変数で受け取る例です。
// IIFE_example3.js
function main(){
const total = ((a, b) => {
return a + b;
})(2, 3);
console.log(`totalは${total}`);
}
// 実行
main();
/* 実行結果
totalは5
*/
この例では,左辺total
で受け取っているのは関数そのものでなくreturn
された結果の値になっていますね。
関数が「即時実行」されたからです。
この違いを見破れるようになるのは,さすがに一朝一夕ではいかないですよね。なんて難しい。。。😓
最初に触れたように,今回この記事を書いたきっかけも,「やっとメリットに気づくことができた」からです。
最後にこの記法が効果を発揮する場面に焦点を戻し,記事をまとめたいと思います。
「ちょっとした処理」を「関数に切り出し」つつ,「使い捨てる」
最初に提示した最終形態を再掲します。
ここまでの積み重ねを踏まえて,もう一度見てみましょう。
// finally.js
function main(){
// システム日付から当日を取得
const today = new Date();
// フォーマット済み年月日を取得
const formattedDate = ((date) => {
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}/${month}/${day}`; // yyyy/mm/dd形式の文字列にする
})(today); // 🌟 ここで即時実行させtodayを投入
// 年度を取得
const fiscalYear = ((date) => {
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月は0から始まるため+1
return month <= 3 ? `${(year - 1)}年度` : `${year}年度`; // 三項演算子で分岐処理
})(today); // 🌟ここで即時実行させtodayを投入
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
// 実行
main();
/* 実行結果
今日は2024/10/03です。
年度は2024年度です。
*/
「だいぶ分かるようになった!」と思ってもらえるとよいのですが。
コメントで補足🌟しているように,この例でも右辺の 「名無し関数」 が即時実行されています。
よって,formattedDate
やfiscalYear
には,関数そのものではなくその実行結果(return
された値)が代入されることになります。
プログラミングで重要なことは, 「変数をシンプルに保つ」 ことであり,そのためにどんどん 「処理を関数に切り出すこと」 が必要なのでした。
「基本のキ」の例ように,main()
の外に別の関数として出してしまうと, 「ちょっとした処理」 にしてはやや手間がかかりすぎる場合があることを説明しました。
そこで,「関数式」とアロー記法を使って,main()
の中でうまく別の関数を定義する方法を導入しました。
では,さらにこれを 「即時関数」 に進化させることが,どのようによいのか。
結論です。
💡 今回のような,「ちょっとした」処理をmain()
の中でやりきってしまいたい場合,かつ,その処理が1回きりである場合,圧倒的に即時関数のメリットが大きくなると思います。
💡 なぜなら, 「関数名」を考えるステップさえ無くすことができるから です。
即時関数を使わない場合をもう一度提示します。
function main(){
const today = new Date();
// 年月日コードを取得する関数
const getFormattedDate = ((date) => {
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月は0から始まるため+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}/${month}/${day}`;
});
// 今日の年月日コードを取得
const formattedDate = getFormattedDate(today);
// 年度を取得する関数
const getFiscalYear = ((date) => {
const year = date.getFullYear();
const month = date.getMonth() + 1; // 月は0から始まるため+1
return month <= 3 ? `${(year - 1)}年度` : `${year}年度`;
});
// 今日の年度を取得
const fiscalYear = getFiscalYear(today);
console.log(`今日は${formattedDate}です。`);
console.log(`年度は${fiscalYear}です。`);
}
// 実行
main();
そう,この getFormattedDate
や getFiscalYear
は,せっかく分かりやすい命名になっているのに,使用されているのは1回きりです。
分かりやすい命名は読み手にとってありがたいものですが,求められる書き手にとっては結構プレッシャーです。
「処理」は一言で表せるものばかりではないけれども,長すぎてもいけないし... どのあたりを落とし所とするのか,相当の時間を要して考え,良さげな英単語を調べ....
そうして生まれた渾身の器,水を注いで,さぁどうぞ! グイッと一杯! ごちそうさま!!!
ほな最初から蛇口で飲めや。
ということですね。例えるならですが🚰
振り返り
今回,このポイントに至ったことで,「処理を関数に切り出す」という作業を,
- 「命名して定義するのか」
- 「名無しで使い捨てるのか」
にさらに分けて考えられるようになりました
何の考えなしにgetFormattedDate
関数を命名して定義してしまうと,もし「別のフォーマットdd/mm/yyで日付を出力したい」という要件が後で出てきた場合に,関数名の競合の問題に直面することになります。
こういう時に即時関数でとりあえず書いておけば,それぞれ使い捨てなので手戻りは発生しないし,もし「同じフォーマットで日付を出力する場面がほかに出てきた」となったら,その時に名前をつけて切り出すことを考え始めれば良いわけです。
こんなふうに,実際の業務におけるコーディングでも,根拠のある判断ができるようになったことで,「お?やっと初心者っぽくなくなったのでは?」と思えるようになり,少し自信がつきました💪
まだまだ知らない仕様,記法がたくさんあるのだと思いますが,貪欲にチャレンジしていきたいと思います!
えらい長くなってしまいました!!お付き合い頂きありがとうございました!! 感想・ご指摘お待ちしております〜〜〜〜!!🐘🐘🐘