ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript 宣言ホイスティングの概要 (例付き)

JavaScript 宣言ホイスティングの概要 (例付き)

不言
不言転載
2019-03-22 09:39:471962ブラウズ

この記事では、JavaScript 宣言の改善について (例とともに) 紹介します。一定の参考価値があります。困っている友人は参考にしてください。お役に立てれば幸いです。

JavaScript 宣言のプロモーション

宣言のプロモーションを分析する前に、次の 2 つの点を理解しておく必要があると思います:

1. エンジンが変数をクエリする 2 つの方法

エンジンが変数を問い合わせる方法は LHS と RHS の 2 通りに分けられ、代入演算の左側の「L」と右側の「R」で意味を大まかに理解できます。 (代入演算にはさまざまな形式があるため、単に「=」の左側と右側として理解することはできません。)

これら 2 つのクエリ メソッドについての私の理解を簡単に説明します。
LHS : 課題 作戦のターゲットは誰ですか? (クエリ変数) ##RHS: 代入操作のソースは誰ですか。 (変数の値を問い合わせる)

これは少し理解しにくいかもしれません、例:

function foo(a){
    //这里存在一个隐式变量分配,LHS查询变量a,并赋值2.
    //隐式a = 2;
    //左边LHS查询变量b,查询作用域中是否存在b这个变量。
    //右边RHS查询变量a的值,将a赋值给b。
    var b = a;
    //返回a,b是RHS查询变量a的值和变量b的值并使用。
    return a + b;
}
//左边LHS查询变量c,查询作用域中是否存在c这个变量。
//右边RHS引用函数foo,将2作为参数传进去。
var c = foo(2);
2. 例外

例外について強調すべき点が 1 つあります。厳密モードです。非厳密モードでは、LHS クエリがトップレベルのグローバル スコープでクエリされた変数を見つけられない場合、その名前の変数を作成してエンジンに返します。

ReferenceError: スコープ決定の失敗に関連しています。 (例: 必要な変数がスコープ内に見つかりません)

TypeError: スコープの決定は成功しましたが、結果に対する操作が不正または不当です。 (例: 非関数型値で関数呼び出しを実行しようとしたり、null または未定義型値のプロパティを参照しようとしています)

例:

"strict"
function foo() {
    console.log(a) //undefined
    console.log(b) //ReferenceError
}
var a = 2;
宣言プロモーション

1. 事前の理解

JavaScript コードを作成するとき、コードが上から下に実行されるように感じることがよくあります。しかし、ステートメントのプロモーションとなると、この考えは崩れます。

例:

a = 2;
var a;
console.log(a);

运行结果为: 2
常識に従ってトップダウンで実行される場合、期待される実行結果は未定義であるはずですが、なぜ 2 なのでしょうか?

これはステートメントのプロモーションの結果です。

2. さらに理解する

ステートメントのプロモーションについて予備的に理解すると、次のコードに遭遇します:

console.log(a);
var a = 2;

运行结果为:undefined
ステートメントのプロモーションについて予備的に理解した後、は当然ステートメントが昇格されると思いますが、宣言時に代入すると変数の値が取得できません。

実際、上記のコードの実行ステップは次のように分解できます。

var a; //声明提升
console.log(a); //打印a的值
a = 2; //对a进行赋值
ステートメントのプロモーションは文字通りのステートメントのプロモーションであり、残りの操作 (代入など) であることがわかります。およびその他のロジック) はまだ残っています。

対応する操作を実行する関数を宣言すると、関数宣言のプロモーションの結果が得られます。これは次のことからわかります。

変数と関数の宣言は、他のコードの前でプロモートされて実行されます。

3. 徐々に理解する

いくつかの実験を通じて、実際には宣言の昇格とは次のことを意味することが徐々に理解できます。

変数と関数の宣言は他のコードで昇格される(現在の機能ドメイン)。

ここで、「関数式ならそれも昇格するのでは?」と思う人もいるでしょう。 ######答えはいいえだ。さらに、名前付き関数式であっても、名前識別子が割り当てられるまでは使用できません。

例:

foo(); //TypeError
bar(); //ReferenceError
var foo = function bar(){};
コードは次のように分解されます:

var foo; //变量声明提升
foo(); //foo对undefined值进行函数调用导致非法操作,故TypeError
bar(); //bar函数并没有声明,故ReferenceError
foo = function bar(){}; //对foo进行赋值
したがって:

関数式は、名前識別子に値が割り当てられるまでは使用できません。

注: 1. 各スコープがプロモートされます。

(したがって、関数内で形成されたスコープにもプロモーション操作があり、プロモーション操作は関数の現在の内部スコープに限定されます) 2. 関数と変数がプロモートされると、関数「プロモートの優先順位付け」が使用されます。
3. 通常ブロック内の関数宣言は、スコープの先頭に昇格されます。
4. 深い理解

「あなたの知らない Javascript」を読んで let を学習する過程で、「宣言が行われる」という説明があることがわかります。 let を使用すると、スコープ内でプロモートされません。宣言は、宣言されたコードが実行されるまで存在しません。

例:

console.log(a);
let a = 2;

运行结果是:ReferenceError: Cannot access 'a' before initialization. //初始化前无法访问"a"
次に、前に実行したコードに戻り、let を var に置き換えると、返された結果は未定義でした。

この 2 つと読書を組み合わせると、let の記事を理解するのに 2 か月かかりました。let が改善されているかどうかについて、より深く理解できるようになりました。

著者は、js 変数を

Create (作成)、Initialize (初期化)、Assign (割り当て) の 3 つの部分に分割します。

上記の操作でレスポンスが異なるのは、let が作成されていないということではなく、実行されていない初期化処理があるためです。また、初期化前に変数 を使用すると、

一時的なデッド ゾーン

が形成されます。 var、let、および function をテストした後、次のように結論付けることができます:

var の作成と初期化は促進されますが、代入は促進されません。

let の作成は促進されますが、初期化と代入は促進されません。

関数の作成、初期化、割り当てが促進されます。

この記事はすべてここにあります。その他の興味深いコンテンツについては、PHP 中国語 Web サイトの JavaScript チュートリアル ビデオ 列に注目してください。

#

以上がJavaScript 宣言ホイスティングの概要 (例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。