関数代入時における括弧の有無による挙動の違い【個人学習まとめ】
今回の問題点
学習中に関数の動きを確認したくて、次のようなコードを書きました。
let function1 = () => ({ name: "太郎" });
let function2 = () => ({ name: "次郎", age: 20 });
function1 = function2;
console.log(function1);
コンソールの結果は次のような想定をしていました。
name: "次郎", age: 20
しかし、実際の結果は私の想定と異なりました。
[Function: function2]
はて?となったので今更ながら調べ、主に2つのポイントがあることと私の間違いに気が付きました...。
ポイント1 afunction11 = afunction2 の意味
今回のコードをもう一度確認してみます。
let afunction1 = () => ({ name: "太郎" });
let bfunction2 = () => ({ name: "次郎", age: 20 });
afunction1 = bfunction2;
console.log(afunction1);
まずfunction1 = function2;
部分ですが、これはfunction1
という変数にfunction2
の関数本体を代入していることを意味します。
この代入により、function1
には関数の実行結果ではなく、関数そのもの(() => ({ name: "次郎", age: 20 })) が代入されました。
ポイント2 console.log(function1) の意味
次にコンソール部分を見てみましょう。
(省略)
console.log(afunction1);
このコードはfunction1
の中身をそのまま出力するコードです。
console.logで関数をそのまま出力する場合は、"[Function: 関数名]" の形式で表示し「これは関数ですよ」という情報を示してくれます。
今回の場合はfunction1
にはfunction2
が代入されているので、コンソールには"[Function: function2]"と表示されます。
ここまできたらコンソールの結果が[Function: function2]
となったことは理解できますね。
私の間違い
では、私が間違っていたのはどこだったのか確認していきましょう。
それはlet function1 = () => ({ name: "太郎" });
の挙動の理解が間違っていました。
私はこのコードを
function1にname: "太郎"というオブジェクトを代入している。
という認識をしていました。
正しくは、function1 に 関数を代入しているということです。
さらにこの間違いを深堀してみると、
- アロー関数(() => {...})
- 関数を呼び出すまでは中身が実行されない
この2点をよく理解していなかったことが判明しました。
今回の例を使いながら、上記2点を再度学習しました。
アロー関数
構文:() => {...}
。
今回のコードlet function1 = () => ({ name: "太郎" });
はfunction1という引数無し関数を定義しているという意味になります。
JavaScriptのfunction
キーワードを使った次のコードと同等になります。
function function1() {
return { name: "太郎" };
}
今回のアロー関数() => ({ name: "太郎" })
では括弧をつかってオブジェクトを返しているため、オブジェクトが直接書かれているように見えました。
しかし、これは関数が実行された時に返す値を示しているだけであり、変数function1
にオブジェクトを定義しているわけではありません。
関数を呼び出すまでは中身が実行されない
function1
という変数は、代入した直後では関数の定義そのものを保持しています。
関数を実行しない限り、{ name: "太郎" }
というオブジェクトは生成されません。
console.log(function1); 関数そのものが表示される
→ [Function: function1]
console.log(function1()); 関数を実行し、オブジェクトが表示される
→ { name: '太郎' }
実際に想定していた結果を得るには?
私が当初想定していた結果をコンソールに出力してみましょう。
まずは私の想定をおさらいです。
name: "次郎", age: 20
これは関数の実行結果になるので、関数そのものを呼び出す必要があると分かりますね。
let afunction1 = () => ({ name: "太郎" });
let bfunction2 = () => ({ name: "次郎", age: 20 });
afunction1 = bfunction2;
console.log(afunction1());
→ { name: '次郎', age: 20 }
これでやりたかったことが実現できました。
JavaScriptは括弧の使い分けが難しい...と感じました。
今回は非常に簡単なコードで気が付くことができたので、この機会に1つ1つ確実に定着させて将来困らないようにしましょう。
Discussion