今天在羣裏吹水時,有羣友提出一個問題。我一看很簡單,就立馬給出了答案:由於存在變量提高,因此輸出undefined。本覺得無人反駁,可確招來口誅筆伐。做爲寫實派的我,一向以來堅持真實是個人使命,豈能容忍這等虛頭巴腦的言論攻擊。遂以此文記之,本在還原真實。奈何文筆拙劣,恐表述不當,誤人子弟。如有不當之處,還請衆佬及時斧正,以正視聽。javascript
就是下面這段代碼:java
var obj = { say: function () { console.log(obj) }() } // 輸出 undefined
爲何是undefined?node
這個問題看似簡單,不值一提,可其實是小孩沒娘,說來話長!編程
儘管如此,我仍是長話短說。很簡單,由於在javascript執行以前,是存在一個「預編譯」或者說是「預解析」這樣的過程,在這個過程中,進行了變量提高。瀏覽器
什麼是變量提高?
變量提高就是將變量名提高到其所在做用域的頂部並賦值爲undefined。與之相關的還有函數提高,不一樣的是,函數提高是將函數名及函數體所有提高到其所在做用域的頂部。編程語言
與其說「預編譯」,「預解析」可能更合理一點。爲何這樣說?
由於在編程語言(如java,C#)當中,代碼都是要先編譯,後執行。而javascript做爲腳本語言,不一樣於編程語言的一點是沒有編譯過程,可是它須要腳本解釋器邊解析邊執行,而腳本解釋器在解釋執行代碼前會先掃描一遍,這個過程就是「預解析」過程。函數
那麼爲何會存在變量提高和函數提高呢?
在ES5當中,沒有塊級做用域的概念,只有全局做用域和函數做用域。聲明變量能夠用var關鍵字,也能夠直接聲明,只不過直接聲明的變量是全局變量,而用var關鍵字聲明的變量在全局做用域下就是全局變量,在函數體內就是局部變量。而且var關鍵字聲明的變量在其所在的做用域下存在變量提高。code
em... 那變量提高跟上面的代碼輸出的結果是undefined有什麼關係呢? 好,請坐下,陳獨秀同窗。對象
咱們來用代碼還原一下真實過程:ip
預解析階段:
生成全局對象,瀏覽器當中是window對象,node環境下是global對象
變量提高:
全局做用域下,變量obj提高到頂部,直接掛在window對象下,至關於window.obj = undefined;
say方法是一個匿名函數。匿名函數的函數體賦值給了變量say。因此變量say也會進行變量提高,它所在的做用域也是全局window下,至關於window.say = undefined;
函數提高:
function(){ console.log(obj); //obj = window.obj = undefined }
執行階段:
1,建立一個執行上下文(execution context),函數壓棧,生成active object(活動對象)
1,執行/解釋上下文中的function,爲變量賦值
2,
參考:https://www.jianshu.com/p/edb2be5866eb
執行階段:
function(){ console.log(obj); //輸出undefined }()