關於對象的前端知識,求解答?
function w() {console.log(w)// 可以訪問w函數本身}
w()
var obj = {"abc":obj //無法訪問本身 為 undefined }
二者都是對象,為啥{}為啥 無法訪問本身么?
因為函數是延遲執行的。
function w() {console.log(w) }
w() // 只有在你調用 w() 的時候,才會去執行 console.log(w)
由於只有在你調用 w() 的時候,才會去執行 console.log(w),所以在時間上,你是先定義 w 再使用 w 的。
但是對象定義就不同了
var obj = {"abc":obj /*立即訪問 obj*/ }
由於你在 obj 還沒有被賦值完,就開始立即訪問 obj 了,所以實際上,你是先使用 obj 再給 obj 賦值的。那麼 "abc" 對應的 obj 實際上是 undefined(因為此時還沒給 obj 賦值)。
其實這是個好問題,大部分前端都遇到過這個問題。
完。
在函數執行前,會有執行上下文創建的過程,創建過程中會將變數定義根據變數定義的方式(var,function,let,const)的不同將變數放在不同的區域里。而用var和function的定義方式存在變數提升特性。
執行上下文中包括變數環境,詞法環境,this,可執行代碼
第一個例子,有兩個執行上下文
function w() {console.log(w) }
w()
全局上下文
變數環境:
w -&> function 可執行代碼:w()w函數上下文變數環境:空可執行代碼:console.log(w)當console.log(w)訪問w時先從當前的執行上下文查找w,沒有去外部上下文查找,因為js是詞法作用域(又稱定義時上下文)的,所有w函數執行上下文的外部上下文會指向全局上下文,所以列印的w是來自於全局上下文的第二個例子
var obj = {"abc":obj }
全局上下文:
變數環境:obj -&> undefined // 變數提升可執行代碼:obj = { abc: obj}當代碼執行時,先運行=右邊的代碼,{ abc: undefined },然後將這個對象的地址存放在obj中,所以就得到了undefined的結果
很正常啊,除開下面的函數/變數聲名提升到函數頂端(覆蓋下層作用域)
在『靜態語言』里也一樣的,雖說 obj.x = obj
這種遞歸數據不是不可以構造,但基本上在 var initializer 里都是不能訪問到正賦值的變數的(不然 var a = a + 1
怎麼辦)
func 定義體里就不一樣了,且不說 JS 語義上是先解析符號所引用的函數值再執行調用(而不是早就靜態存好了全稱名字)所以 func f() 的體里的 f() 調用因為不是先於 f 的定義執行所以(遞歸)使用絕無問題,就是需要靜態解析符號的語言,如果不能在體里引用函數自身,也就寫不了遞歸程序了(只能提前聲明好兩個函數環狀互調真彆扭),上個世紀的某ALGOL版本或許不支持,哈哈。
所謂函數也是對象主要是種概念,不代表語法上毫無區別的,函數體顯然不會立刻執行。
這個是因為javascript的一個特性,變數提升。
什麼是變數提升
因為變數申明是在任意代碼執行前處理的,在代碼區中任意地方申明變數和在最開始(最上面)的地方申明是一樣的。也就是說,看起來一個變數可以在申明之前被使用!這種行為就是所謂的「hoisting」,也就是變數提升,看起來就像變數的申明被自動移動到了函數或全局代碼的最頂上。
變數提升典型例子
var tmp = "tmp";
function f() {
console.log(tmp);
if(false){
var tmp = "false";
}
}
由於變數提升,真實的日誌列印是false,不是tmp。
回答題主的問題
函數定義w提升,當執行w()的之後,w已經定義了。所以可以直接使用。
對於var obj,obj提升為undefined,代碼變成:
var obj=undefined;
obj = {"abc":obj };
雖然obj為undefined,但Chrome 並沒有報錯。此處和樓主的問題不一致。不知道是不是用的其他瀏覽器。
聲明方式不同,var obj是聲明obj變數;而function w(){}是聲明一個w函數;
然而執行var obj = {"abc":obj }時,對象{"abc":obj }中的obj變數還未定義完,即是undefined。
而聲明函數,聲明完不會立刻執行,需要等待w()
推薦閱讀: