>リスト9: lesson04_5.html(UFOを動かすことに成功)
>の20行目で、mainLoop();を呼んでいますが、まだ関数を定義する前の行です。
>なぜ、JavaScriptでこれはエラーにならないのでしょうか?
これは、JavaScriptの「巻き上げ」(hoisting)と呼ばれる機能のおかげです。
https://developer.mozilla.org/ja/docs/Glossary/Hoisting
JavaScriptがなぜこうしたのかといえば、単純に「その方が便利だと思ったから」
なのだと思います。たとえばJavaではメソッドの宣言順は動作に影響せず、
宣言前のメソッドも呼び出せます。もっと古い言語であるCでは、巻数は事前に
定義されていなければ呼び出せず、関数funcAがfuncBを呼び出し、
funcBがfuncAを呼び出すような相互呼び出しをやりたいときには、どちらか片方を
事前に「プロトタイプ宣言」しておく必要がありました(不便です)。
Cで不便だと思われていて、Javaでは改善されたわけですから、Javaに似せた言語である
JavaScriptでは、それはJavaに合わせるでしょう。
もっとも、さすがは変態言語というか、JavaScriptでは「巻き上げ」が
関数だけでなく変数に対しても、しかも関数内の変数に対しても適用されるので、
いろいろ混乱の元になっています。
https://analogic.jp/hoisting/
>私は「完全」初心者ではないのですが、python3では、
>mainloop()
>def mainloop():
> print("Hello, world!")
>と書くと「NameError: name 'mainloop' is not defined」とエラーが出ます。
pythonではなぜ関数を先に定義しておく必要があるかといえば、pythonでは
関数定義のdefは通常の実行文であり、それが実行されて初めて関数が定義されるからです
(逆に言うと、JavaScriptやJavaやCでは、関数定義は実行文ではありません)。
pythonのdefは単なる文なので、たとえばif文の中でdefができます。
a = 10;
if a == 10:
def func():
print("hoge")
else:
def func():
print("piyo")
func()
このコードは、最初にaに代入する値によって、funcの定義が変わります。
CやJavaのような言語では、こういうことはできません。CやJavaでは、関数定義は、
コンパイルの時点で決まります。
JavaScriptはJavaに似せた言語なので、これを引き継いだのだと思います。
ではJavaScriptではif文の中にfunctionは書けないのか、といえば、これがどうも
書けるようで、でも「結果は実装によって一貫性がない」そうです。さすがは変態言語。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/function
| 関数は条件付きで宣言できます。つまり、関数文を if 文の中に入れ子にすることができますが、
| 結果は実装によって一貫性がないので、このパターンを本番コードでは使用すべきではありません。
| 条件付きの関数の作成には、代わりに関数式を使用してください。
私自身、CやJavaのプログラマなので、自分で言語を作ったときには、
型なし言語のcrowbarも、静的型付け言語のDiksamも、関数定義を実行文にはしませんでした。
http://kmaebashi.com/programmer/devlang/index.html
なので、JavaScriptの関数定義については、このようにした気持ちはわかります。
変数定義まで(それもローカル変数まで)同じように巻き上げられるようにしたのは、
正直、理解不能ですが。