JSの事前解析
JSの事前解析の話をする前に、いくつかのC ++のプログラムを探してください
#include <iostream>
using namespace std;
void useGreet(){
greet();
}
void greet(){
cout << "hello" <<endl;
}
int main() {
useGreet();
return 0;
}
复制代码
useGreet宣言されていない関数に()関数呼び出しが、でもその声明の中で()関数を迎えるので、限り、cは、あなたが上記の手順の基礎を知っているだろう++があるとしてコンパイルされていません。これはC ++コンパイラ自体は順番を決めます。のは、JSで書かれたコードの一部を見てみましょう
function useGreet(){
greet();
}
function greet(){
console.log('hello');
}
useGreet();
复制代码
上記のコードは、通常動作であります
これら二つの例JSの事前解析との関係は大きくないですが、また、事前解決JSの内容を反映しているが、
これは、コードをJSでのが見てみましょう
let a = 1;
let fun = function(){
console.log(a);
let a = 2;
console.log(a);
}
fun();
复制代码
営業成績のためのコード
undefined
2
复制代码
次のコードを見てください
let a = 1;
let fun = function(){
console.log(a);
a = 2;
console.log(a);
}
fun();
复制代码
営業成績のためのコード
1
2
复制代码
結果は、2つの非常にマイナーコードの違いは、他の極です実行しているようです。業績を説明する前に、我々は、JS関数と変数モデル内のメモリに保存され、JSの事前解析、jsのスコープチェーンを知っておく必要があります。
メモリモデルに保存されている関数と変数
JSデータは、2つのカテゴリに分類され
- 基本タイプ
- スタックベースタイプがメモリに格納され、オブジェクトはヒープメモリに格納される参照型(オブジェクトタイプ)。
var person = {
name: "Jack",
sex: "man"
}
复制代码
例では、最初に割り当てられ、その後、変数を宣言していた人。前記人物の値
{name: "Jack", sex: "man"}
アドレスのリテラルアドレス値は、ヒープメモリに格納されている人のアドレスであるヒープメモリに格納され、格納者
事前解析されました
JSは、事前に解析され、スコープの前に、JavaScriptコードの実行電流を指し、デフォルトのブラウザが最初にvarと機能の宣言を持つすべての変数の早期の宣言または定義しただろう。すなわち、変数宣言、関数宣言、および割り当ての文の最初の実装であり、その後ために、他のステートメントを実行します。前分析変数および関数は異なる、事前分析変数は割り当てを行わずのみ文た、及び割当による前分析関数宣言が実行されることに留意されたいです。
例えば
fun();
function fun(){
console.log("hello");
}
复制代码
このコードは、通常出力することができhello
、その実行順序、最初fun()
の宣言と割り当て機能し、その後、実行fun()
コールを
以下のコードを見てください
fun(str);
function fun(str){
console.log(str);
}
let str = "hello";
复制代码
上記のコードは、結果として出力することができundefined
、その実行順序、最初fun()
の宣言と割り当て機能、作るstr
声明をした後、実行fun()
呼び出し関数を、次にためSTRの使用上の割り当ての前に、割り当てstrを実行し、その出力STRの初期値undefined
。
スコープチェーン
スコープ鎖である:範囲は可変で使用する場合、この変数のスコープが存在する場合、このスコープ、繰り返しの高い範囲を見つけられない場合は可変絞りは、検索し得ることがあれば、まず、知りますあなたがこれまでの変数を見つけるまで、上記のプロセス。グローバル・ロールは、エラーが見つからなかった場合。
今、あなたは非常に最初に実行するコードの2枚の結果の解釈をすることができます
最初の段落
let a = 1;
let fun = function(){
console.log(a);
let a = 2;
console.log(a);
}
fun();
复制代码
このコードは2つのスコープ、グローバルスコープと同様に、楽しみを持っている()匿名関数のスコープ
コードのグローバルスコープの最初の実装
let a
=> let fun = function
=> fun()
=> a=1
复制代码
そして、コードの関数スコープ、楽しみの実装()関数呼び出しの実行を行います
let a // 预解析
=> console.log(a)
=> a=2
=> console.log(a)
复制代码
第二段落
let a = 1;
let fun = function(){
console.log(a);
let a = 2;
console.log(a);
}
fun();
复制代码
このコードはまた、2つのスコープ、グローバルスコープだけでなく、楽しい()匿名関数のスコープを持っている、唯一の違いは、匿名関数がスコープまたはVAR文を聞かせていないということです
コードのグローバルスコープの実行は、最初の段落と同じです
let a
=> let fun = function
=> fun()
=> a=1
复制代码
しかし、楽しい()関数呼び出しの実行プロセスが異なっています
console.log(a)
=> a=2
=> console.log(a)
复制代码
fun()
範囲は、任意の変数や関数を宣言していなかったので、fun()
スコープには事前に解決プロセス、実行の最初の文ではありませんconsole.log(a)
よう、a
中fun()
範囲のない定義は存在しないので、fun()
ステージは、スコープ上のスコープは見つけることがa
宣言されています1の値は、第1の出力、実行a=2
の、割り当ては、次に行う2であるconsole.log(a)
、場合= 2、出力2
ます。https://juejin.im/post/5cf9cb2df265da1bc8541a5cで再現