他のほとんどの回答が示唆しているように見えるものとは対照的に、これはタイプとはほとんど関係がなく、簡単に推測できます(効率は言うまでもありません)。それはすべて、スコープの明確なセマンティクスに関するものです。
言語構造の複雑なネストを許可する言語では、変数がどこに属しているか、およびどの識別子が同じ変数を参照しているかについて明確な規則を持つことが重要です。そのために、すべての変数には、それが見える場所を定義する明確なスコープが必要です。一般的なケースでは不可能な、変数の明示的な宣言なし (型注釈の有無にかかわらず)。
単純な関数を考えてみましょう (ネストされたスコープの他の形式で同様の例を作成できます)。
function f() {
i = 0
while (i < 10) {
doSomething()
i = i + 1
}
}
function g() {
i = 0
while (i < 20) {
f()
i = i + 1
}
}
何が起こるのですか?伝えるには、どこにバインドされるかを知る必要がありますi
:グローバルスコープまたはローカル関数スコープ? 後者は、両方の関数の変数が完全に分離されていることを意味しますが、前者はそれらを共有し、この特定の例は永久にループします (ただし、グローバル スコープは他の例で意図されているものである可能性があります)。
上記と対比してください
function f() {
var i = 0
while (i < 10) {
doSomething()
i = i + 1
}
}
function g() {
var i = 0
while (i < 20) {
f()
i = i + 1
}
}
対
var i
function f() {
i = 0
while (i < 10) {
doSomething()
i = i + 1
}
}
function g() {
i = 0
while (i < 20) {
f()
i = i + 1
}
}
これにより、考えられるさまざまな意味が完全に明確になります。
一般に、(1) プログラマーが実際に意図したことを推測でき、(2) プログラムの拡張またはリファクタリングの下で十分に安定している、適切なルールはありません。プログラムが大きく複雑になるほど、厄介になります。
毛むくじゃらのあいまいさと驚くべきエラーを回避する唯一の方法は、変数の明示的な宣言を要求することです。これは、すべての合理的な言語が行うことです。(これは言語設計の 101 であり、50 年間続いていますが、残念ながら、新しい世代の言語「設計者」が、特にいわゆるスクリプト言語で、同じ古い過ちを何度も繰り返すことを妨げていません。難しい方法でレッスンを行い、間違いを修正します。たとえば、ES6 の JavaScript など)。