ES6 インポートにより変数が昇格されます。変数ホイスティングとは、変数宣言をそのスコープの先頭に昇格させることです。 js はコンパイル フェーズと実行フェーズを経る必要があります。コンパイル フェーズでは、すべての変数宣言が収集され、変数は事前に宣言されますが、他のステートメントの順序は変更されません。したがって、コンパイル フェーズでは、最初のステップはすでに実行されています。 2 番目の部分は、ステートメントが実行フェーズで実行された場合にのみ実行されます。
このチュートリアルの動作環境: Windows 7 システム、ECMAScript バージョン 6、Dell G3 コンピューター。
JavaScript はシングルスレッド言語であるため、実行は順番に実行する必要があります。ただし、1 行ずつ分析して実行するのではなく、部分ごとに分析して実行し、最初にコンパイル フェーズが実行され、次に実行フェーズが実行されます。コンパイル段階中、コードが実際に実行される数ミリ秒前に、すべての変数と関数の宣言が検出され、Lexical Environment と呼ばれる JavaScript データ構造内のメモリに追加されます。したがって、これらの変数と関数は、実際に宣言される前に使用できます。
簡単な例から始めましょう:
a = 2; var a; console.log(a);
上記のコードは何を出力しますか? このコードが上から下に実行されると、間違いなく未定義の出力が出力されますが、JavaScript は次のような言語ではありません。トップダウンで実行されます。 このコードの出力は 2 ですが、これは予想外でしょうか?では、なぜこのようなことが起こっているのでしょうか? 重要な点は、変数プロモーションにあります。現在のスコープ内のすべての変数の宣言をプログラムの先頭に上げます。したがって、上記のコードは次のコードと同等です。これでより明確になりますか?
var a; a = 2; console.log(a);
次に、別の例を見てみましょう:
console.log(a); var a = 2;
このコードは何を出力しますか?出力2? 実際、このコードは unknown を出力します。これが理由です?先ほども言いましたが、JavaScript では変数の宣言は先頭に昇格しますが、代入文は昇格しません。js の場合、var a = 2 は 2 段階の解析:
var a; a = 2;
そして、js は文 var a のみをプロモートするので、今のステートメントは次と同等です:
var a; console.log(a); a = 2;
変数昇格という現象はなぜ起こるのでしょうか? なぜなら、js は他の言語と同様、コンパイルと実行の段階を経る必要があるからです。 js がコンパイル段階にあるとき、すべての変数宣言を収集して事前に変数を宣言し、他のステートメントの順序は変更されないため、コンパイル段階では最初のステップが実行され、2 番目の部分が実行されます。ステートメントが実行フェーズで実行される場合のみ。
ES6 インポートにより、変数プロモーションが発生します。
たとえば、次のテスト コードでは、
// a.js console.log('I am a.js...') import { foo } from './b.js'; console.log(foo); // b.js console.log('I am b.js...') export let foo = 1;
が a.js を実行します。
// node -r esm a.js I am b.js... I am a.js... 1
出力される結果は、「I am b.js..」です。 .' が最初に表示され、次に 'I am a.js...' が再び表示されます。これが変数プロモーションの現象です。
これは、ES6 が言語標準レベルでモジュール関数を実装しているためです。そのため、a.js がプリコンパイルされ、キーワード import が見つかると、最初に b.js が読み込まれるため、「私は b.js です」となります。 ...』。
全体のプロセスは次のとおりです。
変数プロモーションの生成は、実際には変数オブジェクトの作成プロセスに関連しています。
変数オブジェクトの作成手順
変数オブジェクト(Variable Object)の作成は、以下の手順で順番に行われます。
現在のコンテキストの関数宣言、つまり function キーワードを使用して宣言された関数を確認してください。変数オブジェクトに関数名を含む属性を作成します。属性値は、関数が配置されているメモリ アドレスへの参照です。関数名属性がすでに存在する場合、その属性は新しい参照によって上書きされます。
現在のコンテキストで変数宣言を確認してください。変数宣言が見つかった場合は、変数オブジェクト内に変数名を持つ属性が作成されますが、属性値は未定義です。変数名の属性が既に存在する場合、同名の関数が未定義に変更されるのを防ぐため、そのままスキップされ、元の属性値は変更されません。
function ステートメントは、var ステートメントよりも高い優先順位を持ちます。
function test() { console.log(a); console.log(foo()); var a = 1; function foo() { return 2; } } test();
test() の実行コンテキストから直接理解を開始します。
// 创建过程 testEC = { // 变量对象 VO: {}, // 作用域链 scopeChain: {} } // VO 为 Variable Object 的缩写,即变量对象 VO = { arguments: {...}, foo: <foo reference> // 表示foo的地址引用 a: undefined }
test() の実行結果は、
// node -r esm demo01.js undefined 2
実際には、上記のコードdemo01.jsは、この実行シーケンスになります、
function test() { function foo() { return 2; } var a; console.log(a); console.log(foo()); a = 1; } test();
[関連する推奨事項: JavaScript 学習チュートリアル #]
以上がes6 インポートは変数をプロモートしますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。