1. ローカル変数は最初に使用されてから宣言されます。これは、同じ名前の外部変数には影響しません。
次のようにコードをコピーします。
var x = 1; // --> 外部変数 x
関数 fn(){
alert(x); // --> 未定義のローカル変数 x が最初に使用されます
var x = 2; // 後で宣言して代入します。
}
fn();
アラート(x); // --> 1<BR>
1 点目は、関数 fn の最初の文が x を出力し、x が 2 番目の文で定義されていることです。これは JS では許可されており、ここで許可されているということは、プログラムが構文エラーなしで実行できることを意味します。
ただし、C や Java などの他の言語では許可されません。変数は使用前に宣言する必要があります。
次のようにコードをコピーします。
パブリック クラス テスト {
public static void main(String[] args) {
System.out.println(x); // 最初に使用します。
int x = 10; // 宣言後
}
}
Java では、コンパイラによってエラーが表示され、プログラムは実行できません。
2 点目は、関数 fn 内のローカル変数 x は外部変数 x に影響を与えないということです。つまり、fn のアラート出力は 1 ではなく、未定義になります。
次に、仮パラメータは関数名よりも優先されます。
次のようにコードをコピーします。
関数 fn(fn){
アラート(fn);
}
fn('こんにちは'); // --> "こんにちは"
関数名と仮パラメータは fn と同じ名前であり、出力は文字列 "hello" ですが、関数 fn の関数本体 (fn.toString()) ではないことがわかります。
第三に、仮パラメータは引数よりも優先されます。
次のようにコードをコピーします。
関数 fn(引数){
アラート(引数);
}
fn('こんにちは'); // --> 「こんにちは」<BR>
引数オブジェクトは関数内で直接使用でき、言語自体によって提供される特別な識別子です。
ここでは、仮パラメータが同じ名前で宣言されていることが起こります。出力が「[object Object]」ではなく「hello」であることがわかります。つまり、仮パラメータの引数が、言語自体によって提供される実際の引数をカバーしています。
4. 仮パラメータは、宣言されていても割り当てられていないローカル変数よりも優先されます。
次のようにコードをコピーします。
関数 fn(a){
変数a;
アラート(a);
}
fn('こんにちは'); // --> "こんにちは"
関数 fn の仮パラメータは a です。関数の最初の文では、ローカル変数 a を宣言するだけで、値は割り当てられません。出力結果が undefine ではなく "hello" となっていることから、宣言されただけで値が代入されていないローカル変数 a よりも仮パラメータ a の方が優先度が高いことがわかります。
5. 宣言および代入されたローカル変数は、仮パラメータよりも優先されます。
次のようにコードをコピーします。
関数 fn(a){
変数 a = 1;
アラート(a);
}
fn('こんにちは'); // --> "1"
関数 fn の仮パラメータは a です。関数の最初の文では、ローカル変数 a を宣言し、それに値 1 を割り当てるだけです。出力結果が「hello」ではなく「1」であることから、宣言して代入したローカル変数 a が仮パラメータ a よりも優先度が高いことがわかります。
6. 仮パラメータを同名のローカル変数に代入した場合
次のようにコードをコピーします。
関数 fn(a){
変数 a = a;
アラート(a);
}
fn('こんにちは');
まだ実行しないで、結果を推測してください。ポイント 5 に従う場合: 宣言および割り当てられたローカル変数は、仮パラメータよりも優先されます。その場合、 a は未定義になります。しかし実際には、a は「hello」です。つまり、右側の a は仮パラメータ a、左側の a はローカル変数 a です。
ここでの 2 つの a は互いに干渉せず、どちらも他方をカバーしません。これは、先ほど述べたことと矛盾しています。割り当てられたローカル変数は、仮パラメータよりも優先されます。しかし、var a = a の後に a が未定義になることを望まないため、エンジンは私たちが望むことを実行します。