function a() { var a = 1; function b() { a = 10; return; function a() {} } b(); log(a); } a();
輸出結果(下一行,拖動或ctrl+A)
■■■■■■■ 輸出: 1 ■■■■■■■
解析:
昨天去面試,就掉到上浮的坑裏,本來是知道這個問題的,但是不太熟練又被迷惑。
最後面試官給我說,變量上浮,是在定義的時候產生的,執行時不存在這個問題。
來看這個題,a()函數 可以重新這樣寫
function a(){ function b()//上浮 { function a(){};//上浮至最高,變量a是函數 a=10;//變量a又被賦值爲10 return; } var a;
a=1;
b();//執行b(),因爲b上浮到頂部,所以先執行了b()中的a=10,然後才執行了上一行的a=1,所以最終結果是1 log(a); } a();
_______________________________________________________
(分割線,在這個題的基礎上修改一下)
function test() { //a() return console.log(a,b); function a(){console.log(test)} var b = 'ssss'; } test();
這個裏面函數a()和變量b的定義都是在return之後,輸出結果是什麼?
如果把a()的註釋去掉,會得到什麼?
輸出結果: function a()內容和undefined
這說明,在函數執行前(或者說函數執行時),function a()形式的聲明,可以提升至作用域頂部,而var就不具備這個作用。
如果把註釋去掉,執行a(),則會報錯test未定義,說明函數只有在執行時纔會檢查調用的變量是否存在,可以推想,未執行的函數內部如果有錯誤也是不會報錯的,請看下面這個代碼:
function b(){ asdfasdfasdf as dfa sdf asdfasdfasdffas dfa }
不執行b(),是不會出現任何錯誤的。
再看一段代碼:
function a() { var a = 1; function b() { console.log(a); a = 10; console.log(a); return; function a() {a=5;} } b(); console.log(a); } a();
輸出:
function a()
10
1
這是因爲return後面的function a()提升至頂部,並在當前函數作用域內聲明瞭一個本地局域變量a,a=10賦值給該局域變量。
如果把return後面的function a()註釋掉,則輸出
1
10
10
這兩種輸出說明,function a()具有和var a同樣的作用,指定了a的作用域爲函數體內。修改一下,比如:
function a() { var a = 1; function b() { console.log(a) var a = 10; console.log(a) return; } b(); console.log(a); } a();
這裏b()函數體內的var a=10將變量a的作用域設定在函數體內,a=10的賦值就會在b函數內執行,而不會達到外部的a()函數。等價於:
function a() { var a = 1; function b() { var a; console.log(a) a = 10; console.log(a) return; } b(); console.log(a); } a();
好了,看明白上面的內容,再來看餐後甜點:
var foo = 1; function Main(){ console.log(foo); var foo = 2; console.log(this.foo); this.foo = 1; } Main(); new Main();
輸出有什麼不同?