標籤:類型 變數 asc type 全域變數 oba func 未定義 style
(function() { var x=foo(); var foo=function foo() { return ‘foobar‘ }; return x; })();
這段代碼運行後報錯:Uncaught TypeError: foo is not a function
原因在於變數foo的聲明提升,後面的賦值,函數運算式不會提升,因此當代碼運行到 var x=foo(); 時,
foo()是未定義的。
可以把 var x=foo(); 放到 變數 foo 後再執行:
(function() { var foo=function foo() { return ‘foobar‘ }; var x=foo(); return x; })();
函式宣告整個提升到範圍頂部,比如這樣寫:
(function() { var x=foo(); function foo() { return ‘foobar‘ } return x; })();
再看一個例子:
var foo = {n:1}; (function (foo) { //注意這裡,傳進參數 foo console.log(foo.n); foo.n=3; //全域變數重新賦值, var foo={n:2}; //局部變數foo進行重新賦值 console.log(foo.n); })(foo); console.log(foo.n);//全域變數已經是 n:3
- 第一步:進行先行編譯,var全域變數foo、匿名函數 function、var局部變數foo
- 第二步:代碼自上而下、自左向右執行計算:
- 對全域變數foo進行賦值foo={n:1};注意:此值為對象,屬於參考型別;
- 匿名函數傳入參數foo={n:1}自執行;
- console.log(foo);打出數字1;
- 由於存在foo局部變數,那麼對foo變數進行賦值foo={n:3},同時更改了參考型別的參數值,全域foo變數被重新賦值foo={n:3};
- 對局部變數foo進行重新賦值foo={n:2};
- console.log(foo);打出數字2;
- 全域變數foo={n:3},因此,console.log(foo);打出數字3;
關於var x1=foo(); 和 var x2=foo; 有沒括弧的區別
函數是一種叫做function參考型別的執行個體,因此函數是一個對象。對象是儲存在記憶體中的,函數名則是指向這個對象的指標。
函數可以作為參數傳入別的函數,也可以作為一個函數的傳回值,也可以被重新賦值。
簡單來說,x1是函數foo()的傳回值,x2是函數foo()本身。
(function() { var foo=function foo() { return ‘foobar‘ }; var x=foo; return x; })();//function foo() { return ‘foobar‘ }
JavaScript 變數聲明提升