2

JavaScript の変数ホイストについて質問があります。

次の例を考えてみましょう: </p>

var myName = "Richard"; // Variable assignment (initialization)
​
​function myName () {
console.log ("Rich");
}
​
console.log(typeof myName); // string 

なぜがstringtypeof myNameとして返されるのか、実際には混乱しています。

私の理解では、例は次のように処理されます。

  1. 最初に関数宣言 ( function myName ()) が一番上に持ち上げられ、次に
  2. JS インタープリターはその行を読み取りますvar myName = "Richard"(関数宣言が変数宣言よりも優先されるため)。ただし、"myName" という名前のプロパティが既に存在するため、このステートメントは無視されます。

したがって、(文字列ではなく)関数typeof myNameとして返される必要があります。

私の理解はどこが間違っていますか?

4

5 に答える 5

0

他の回答に加えて、次の方法で関数を宣言する場合、注意すべき点は次のとおりです。

var myName = function() {
  console.log('Rich');
}

または単に

myName = function(){
  console.log('Rich')
}

「function myName . . .」構文とは対照的に、typeof myName は「function」を返します。

于 2015-08-27T21:17:27.240 に答える
0

2年が経過しましたが、おそらくそれは誰かにとってまだ関連性があります

  • 関数宣言のコンテキストをスキャンする

    • 見つかった関数ごとに、変数オブジェクトにプロパティを作成します
    • 関数名が既に存在する場合、参照ポインターの値は上書きされます
  • 変数宣言のコンテキストをスキャンします

    • 見つかった変数宣言ごとに、変数名である変数オブジェクトにプロパティを作成し、値を未定義として初期化します
    • 変数名が変数オブジェクトに既に存在する場合は、何もせずにスキャンを続行します

ただし、これはグローバルスコープではそうではないようです。つまり、オブジェクトを定義すると、出力は本来あるべきものとまったく同じになりますが、グローバルスコープで同じものを定義すると、そうではありません....まだこれに頭を悩ませようとしています

于 2016-09-17T12:06:22.253 に答える
-1

変数と関数の定義が一番上に移動したためHoisting、次のようになります。

var myName;
// moved to top
function myName () {
  console.log ("Rich");
}

// next your code
myName = "Richard";

console.log(typeof myName); // string 

コードを次のように書き換えると:

var myName = "Richard"; // Variable assignment (initialization)
​
myName = ​function () {  // Variable redefinition
  console.log ("Rich");
}
​
console.log(typeof myName); // function

変数のみが次のとおりであるため、変数はmyName関数になりました。myNamehoisted

var myName;

myName = "Richard";     // Variable assignment (initialization)
myName = ​function () {  // Variable redefinition
  console.log ("Rich");
}
​
console.log(typeof myName); // outputs 'function'
于 2014-11-04T07:36:05.830 に答える
-1

「持ち上げる」という考えは、何が起こっているのかを理解するための悪い方法です。言い換えれば、私の意見では、「巻き上げ」は巻き上げの悪い説明です。

実際に起こっているのは「巻き上げ」ではありません。実際に起こっていることは、javascript がコンパイル フェーズと評価フェーズの 2 つのフェーズでコードを実行することです。JavaScript コミュニティはこの現象を「ホイスト」と呼んでいますが、ほとんどの人はなぜホイストをホイストするのか理解できていません。

実際に何が起こるかは、巻き上げのアイデアよりも簡単に説明できます。ルールは次のとおりです。

  1. Javascript は常にトップダウンでコードを解析します。コードを並べ替えることはありません (ホイストすることはありません)。

  2. 実行には、コンパイルと評価の 2 つのフェーズがあります。

  3. すべての宣言はコンパイル段階で処理され、コンパイル段階では式は評価されません (「評価」は評価段階で行われるため)。

  4. 評価が必要なすべての式とその他のものは、評価フェーズで処理されます。

ルール 1 を思い出してください。すべての解析はトップダウンで行われ、バックトラッキングや巻き上げはありません。

あなたの例を取り上げて、javascript のコンパイルと評価フェーズを念頭に置いて理解しようとしましょう。

    var myName = "Richard"; // Variable assignment (initialization)
​    
 ​   function myName () {
       console.log ("Rich");
    }

​    console.log(typeof myName); // string 
  1. コンパイル段階では、インタプリタは変数の宣言を認識します。この変数にメモリ領域を割り当て、値を割り当てますundefined

  2. コンパイル段階では、インタープリターは関数の宣言を認識します。また、関数名が変数名を隠していることにも注意してください。したがって、関数「myName」が作成されます (これは、この時点で変数myNameが関数を指していることを意味します)。

  3. コンパイル フェーズが終了します。いよいよ評価フェーズに入ります。

  4. 評価フェーズでは、インタープリターは文字列を に割り当てていることを確認しますmyName

  5. 宣言はコンパイル段階で処理されるため、関数宣言に到達したときに評価するものは何もありません。

  6. 評価フェーズでは、インタプリタは typeof を console.logging するのを見ますmyName。最後に割り当てられたのは文字列だったので、「文字列」と表示されます。

myName文字列の割り当てを削除すると、typeof "function" になることに注意してください。その場合、最後に割り当てられるのは宣言された関数だからです。

実行の 2 つのフェーズによって引き起こされるその他の微妙な点については、この関連する質問を参照してください: JavaScript 関数の宣言と評価順序

于 2014-11-04T07:47:16.533 に答える