js 變數 函式提公升 與js的預編譯有關

2022-08-27 01:09:07 字數 3010 閱讀 5153

參考**:

先簡單理解下作用域的概念,方便對變數與函式提公升的概念的理解

function

foo()

console.log(x);

}foo();

//2

結果為2,可見js中並沒有塊級作用域的概念

可以使用下面的方法創造自己的作用域,這樣不會干擾到外部變數

function

foo() ());

}console.log(x);

}foo();

//1

結果為1,可見js中的作用域是以函式為邊界的

1.變數提公升:

變數提公升與js的預編譯有關,下面通過例子輔助說明

var a = 100;

var b = 200;

function

foo()

foo();

js預編譯時會先在當前作用域中找到var宣告的變數分配空間,賦值為undefined,如果找不到就會到下一級作用域中找

上面的**的等價**如下:

var a = 100;

var b = 200;

function

foo()

foo();

這樣看是不是容易理解多了。第一行var宣告了a,但是沒有賦值,因此為undefined,下面列印10、1也就順理成章了。

至於變數b,它在當前作用域中找不到,因此需要到外層作用域中找,在window下找到了變數b,可以看到它的值為200

2.函式提公升

首先要明確兩點:

<1> 只有函式宣告才會進行函式提公升

<2> 函式提公升會將函式體一起提公升上去,這點與變數提公升有所不同

下面來證明函式表示式不能進行函式提公升:

~function

() ()

}()

函式前面加個~的目的是將函式宣告變成函式表示式,實際上也可以加其它運算子,比如+,-,!等,總之這個函式宣告被變成了函式表示式。

從列印結果來看第乙個alert出的是undefined,說明next根本沒有發生函式提公升。

下面來接著驗證:

a();//

123var a = function

()a();

//321

function

a()

從結果可以看出,先列印出來的反而是放在後面的a(),上面**的等價表示如下:

var a = function

a()a();

a = function

()a();

那麼如果當變數提公升與函式提公升同時發生的時候,哪個的優先順序更高呢?我們來做個實驗:

function

fn()

console.log(a);

}fn();

//function a(), 2

從列印順序中可以看出,函式提公升比變數提公升優先順序高,因為函式提公升是將函式體整體提公升,提公升上去後立馬賦值。等價**如下:

function

fn()

console.log(a);

a = 2;

console.log(a);

}fn();

下面再來幾個有趣的例子:

b = 100;

function

b()b();

//b is not a function

//函式提公升導致的

////////////////////

b = 100;

var b = function

()b(); //2

//函式表示式不存在函式提公升

function

change()

var foo = function

()var

fn;}

change();

//fn提公升了,foo沒有提公升

下面還有幾個思考題:

1.

var a = 1; 

function

b()

} b();

//? function a() {}

console.log(a);//

? 1

2.

a = 10;

(function

a()})();

這段**難以理解,測試**為:

var a = 10;

var b = 20;

(function

b())();

console.log(a);

console.log(b);

網上有一段解釋是這樣的(這樣的**太難理解,最好還是函式和變數不要同名):

感覺樓主的理解還不夠深入,正確理解應該是經過以下過程:

當進入執行上下文(**執行之前)時,vo(變數物件)裡已經包含了下列屬性:

函式的所有形參(如果我們是在函式執行上下文中)

— 由名稱和對應值組成的乙個變數物件的屬性被建立;沒有傳遞對應引數的話,那麼由名稱和undefined值組成的一種變數物件的屬性也將被建立。

所有函式宣告(functiondeclaration, fd)

—由名稱和對應值(函式物件(function-object))組成乙個變數物件的屬性被建立;如果變數物件已經存在相同名稱的屬性,則完全替換這個屬性。

所有變數宣告(var, variabledeclaration)

— 由名稱和對應值(undefined)組成乙個變數物件的屬性被建立;如果變數名稱跟已經宣告的形式引數或函式相同,則變數宣告不會干擾已經存在的這類屬性。

3.

function

a(i) ;

a(10);

**分析如下:

function

a(i) ;

a(10);

JS 變數或函式的預編譯

1.變數的提前編譯 showname 變數提前 function showname 注 在以上 中,第乙個輸出只是宣告了a,並沒有進行初始化賦值,因此其值為undefined,在這裡稱為預編譯。2.函式的提前編譯 1 如上 中的showname 從上向下執行,先執行showname 但按理說這個方法...

JS 函式預編譯

1 語法分析 2 預編譯 3 解釋執行 預編譯四部曲 1.函式在執行的瞬間,生成乙個執行期上下文 active object 簡稱ao 2.分析引數 2.1 函式接收形式引數,新增到ao的屬性,並且這個時候值為undefine,例如ao.age undefined 2.2 接收實參,新增到ao的屬性...

JS 變數提公升與函式提公升

在 es6 出來之前,沒有塊級作用域,只有全域性作用域 和 函式作用域。變數提公升指的是 將變數宣告提公升到它所在作用域的最開始部分。例子 console.log foo undefined var foo 變數提公升 console.log foo 變數提公升 相當於 var foo consol...