我理解的JavaScript預編譯

JavaScript是一門單線程,解釋型,弱類型的動態語言,解釋一行執行一行。函數

JavaScript執行過程首先先語法分析,就是分析一遍代碼有沒有語法錯誤,解析期間不會執行代碼。接着就開始預編譯,預編譯完了就開始一行一行執行代碼。線程

預編譯過程會建立兩個對象,一個是全局的Global Object對象,簡寫GO,另外一個是函數的Activation Object對象,簡寫AO。兩個只是做用域不一樣,建立步驟是同樣的。cdn

預編譯大概步驟:對象

建立AO、GO對象ip

找形參和變量聲明,做爲屬性名,值爲undefined作用域

統一實參和形參it

找函數聲明,賦值函數體io

說的抽象了,咱們以一個函數爲例:console

function fn(a) {編譯

console.log(a);

var a = 1;

console.log(a);

function a() {};

console.log(a);

var b = function () {};

console.log(b);

function c() {}

}

fn(3);

建立AO = {}

把形參和變量聲明做爲屬性名和賦值undefined

AO = {

a: undefined,//參數a var a function a

b: undefined,//var b

c :undefined,//function c

}

統一形參和實參

AO = {

a: 3,

b: undefined,//var b

c :undefined,//function c

}

找函數聲明,賦值函數體

AO = {

a: function a(){},

b: undefined,//var b

c: function c(){},

}

接着就是一行一行執行了:

function fn(a) {

console.log(a);

var a = 1;

console.log(a);

function a() {};

console.log(a);

var b = function () {};

console.log(b);

function c() {}

}

fn(3);

AO = {

a: function a(){},

b: undefined,

c: function c(){},

}

當執行第一個打印的時候,打印出function,而後var a = 1的時候,聲明已經聲明過了,其實就a = 1,因此第二個打印是1,到了聲明函數a的時候已是聲明過的,再打印也是1,至於b和c就不用多說了。最後結果就是f a(){}、一、一、f(){}。

其實能夠記住幾個點,函數聲明是總體提高,變量聲明只是聲明提高。還有,若是一個變量沒有聲明,那麼默認就是window的:

(function fn() {

var a = b = 10;

}());

console.log(b);//10

console.log(a);//err

b沒有直接var聲明,那麼就是全局window的,因此b能打印,a就會報錯。

有個點要注意,JavaScript在預編譯階段, 會解釋函數聲明, 但卻會忽略表式。好比一個自執行函數:

(function fn() {

}())

當執行到有()的時候,JavaScript會去對這個表達式求解獲得返回值,返回的是一個函數且有(),因此直接執行了,其它的自執行函數原理都是這樣的,都是經過表達式。函數轉換爲表達式的方法並不必定要靠分組操做符(),咱們還能夠用void操做符,!操做符+操做符等等。

+function () {}()

void(function () {alert(0)}())

console.log(function () {alert(0)}())

這些表達式均可以當即執行函數,就算+號獲得的最終結果是NaN,可是在隱式轉換以前卻要先執行函數。

函數參數你能夠看做在函數裏面隱式的聲明瞭一個變量a:

function fn(a) {

var a;

console.log(a);//3

}

fn(3)

並且函數參數裏面在預編譯過程當中,會造成一個臨時做用域,在預編譯完了以後會消失:

function fn(a, b = function () {a = 5}) {

console.log(a);//3

b();

console.log(a);//3

}

fn(3)

(a, b = function () {a = 5})這是一個臨時的做用域,這裏面的參數a就算改變了也影響不到原來的參數a。只有在參數做用域裏面纔有效果:

function fn(a, b = (function () {a = 5})()) {

console.log(a);//5

console.log(a);//5

}

fn(3)

相關文章
相關標籤/搜索