這是我申請博客園寫的第一篇文章,想把這兩天學習的關於js的變量和函數提升機制(hoisting)記錄下來。
從網上看到這么一段代碼:
var c = 2;
function c(){
c = 22;
console.log("c="+c);
}
c();//會報錯,變量提升機制導致的(c is not a function)
問運行結果是什么,然后不假思索的就以為是22,因為c=22這行看起來就是對外面的全局變量c重新定義了
但是實際上不是的,這句話不會執行到c()的時候會報錯(number is not a function),有點蒙蔽,這是怎么了,查了好久,才知道js有個提升機制,變量和函數(函數聲明的方式有提升機制,函數表達式沒有這個機制)都有提升機制,而且函數提升機制的優先級高於變量的,這也就是說當函數名和變量名相同的時候,拿上面這個例子來說,c被提升到代碼最前端,並且被賦值為一個函數,然后才會 被賦值為2,上面的代碼等效於下面這個:
var c = function c(){
c = 22;
console.log("c="+c);
};
c = 2;
c();
執行的時候,c先被賦值為一個函數,然后緊接着又被賦值為數字2,這樣在這句賦值語句下面執行c()的時候,c就不是函數了,而是數字,如果在c = 2;這句話的上面執行c()的話,就沒有問題了,結果是c = 22;
再來看另一個問題,函數聲明和函數表達式有什么不同,就是下面這兩種情況:
d();//1
function d(){//方式1
alert("1");
}
d();//undefined is not a function
var d = function(){//方式2
alert("1");
};
這兩種聲明函數方式不同之一在於:
方式1可以在d聲明之前使用d()來調用函數,方式2卻不可以
這個也是可以用變量提升機制來解釋的,方式1的寫法和下面這個等價:
var d = function d(){
alert("1");
};
d();
所以執行沒有問題,但是第二種寫法的函數就沒有變量提升機制,好像也可以用這個方式來解釋,第二種寫法等價於下面這樣:
var d;
d();
d = function(){
alert("1")
};
這樣的話,執行d()的時候,d還沒有被定義為函數,只是被聲明了,所以會執行報錯。(這樣應該可以解釋的通,不對的地方,請務必讓我知道)
來看個復雜點的例子:
var a = 1;
function b() { //變量提升機制:如這個例子所示,執行b()時
console.log(a); // function a(){}
a = 10; //這可不是對外面的全局變量a定義哦
console.log(a); //10(局部變量)
var a = 11;
console.log(a); //11(局部變量)
return;
function a(){
alert("abc");
}
}
b();
console.log(a); //1(全局變量)
上面的例子等價於下面這樣:
var b = function b(){
var a = function a(){
alert("abc");
}
console.log(a);
a = 10;
console.log(a);
a = 11;
console.log(a);
return;
}
var a;
a = 1;
b();
console.log(a);
不知道寫的這點東西對大家有沒有一點幫助呢?