var x = 1;
は実際には次のように解釈されます:
function foo() {
var x;
bar();
結果は、ステートメントが実行されるかどうか。次の 2 つのコードは同等です:
関数 foo () { if (false) {
var x = 1;
}
return;
関数 foo() {
var x, y;
if (false) {
x = 1;
y = 1;
宣言の代入部分がホイストされていないことに注意してください。宣言された名前のみが昇格されます。これは、関数本体全体もホイストされる関数宣言とは異なります。ただし、関数を宣言するには通常 2 つの方法があることに注意してください。次の JavaScript コードを考えてみましょう:
コードをコピーします
コードは次のとおりです:
alert("これは実行されますrun! "); }
}
test();
ここでは、関数宣言のみが関数本体と一緒にプロモートされ、関数式のみがプロモートされます。 be昇格 名前と関数本体は、代入ステートメントの実行時にのみ割り当てられます。
上記は巻き上げの基本をすべて網羅していますが、それほど複雑でわかりにくいとは思えませんね。ただし、これは JavaScript であり、特殊な場合には常に少し複雑な問題が発生します。
名前解決の順序
覚えておくべき最も重要な特殊ケースは、名前解決の順序です。名前をスコープに入れるには 4 つの方法があることに注意してください。上にリストした順序は、解析される順序です。一般に、名前がすでに定義されている場合、その名前は、異なる属性を持つ同じ名前の別の名前によって上書きされることはありません。これは、関数宣言が変数宣言よりも優先されることを意味します。ただし、これはこの名前への割り当てが無効であるという意味ではなく、宣言された部分が無視されるというだけです。いくつかの例外があります:
組み込みの名前引数は少し奇妙な動作をします。仮引数の後、関数宣言の前に宣言されているようです。これは、パラメータが未定義であっても、arguments という名前の仮パラメータが組み込み引数よりも優先されることを意味します。これは悪い機能です。引数を仮パラメータとして使用しないでください。
これを識別子として使用しようとすると構文エラーが発生しますが、これは良い機能です。
同じ名前の仮パラメータが複数ある場合、たとえ未定義であっても、リストの最後にあるパラメータが最も高い優先度を持ちます。
関数式に名前を付ける
関数宣言ステートメントと同じように、関数式で関数の名前を定義できます。ただし、これは関数宣言にはならず、名前はスコープに導入されず、関数本体はホイストされません。意味を説明するためのコードを次に示します。
コードをコピー
コードは次のとおりです:
foo() // 有効 bar();
baz(); // 有効な
spam(); // ReferenceError "スパムが定義されていません"
この知識を使ってコーディングする方法
これで理解できました。スコープとホイスティング、これは JavaScript コードの記述にとって何を意味しますか?最も重要なことは、変数を宣言するときに常に var ステートメントを使用することです。各スコープの先頭では 1 つの var のみを使用することを強くお勧めします。これを無理にやっておけば、昇進に関する問題に悩まされることはありません。ただし、そうすることで、現在のスコープでどの変数が実際に宣言されているかを追跡することがより困難になります。 JSLint では onevar オプションを使用することをお勧めします。これまでの提案をすべて実行すると、コードは次のようになります:
コードをコピーします
コードは次のようになります:
/*jslint onevar: true [...] */
function foo(a, b, c) {
var x = 1,
bar,
baz = "something";
}
標準の内容
これらのことがどのように行われるかを理解するには、