1. 程式人生 > >js作用域以及作用域鏈的理解

js作用域以及作用域鏈的理解

以前一直以為自己對作用域和作用域鏈瞭解的比較清晰,直到最近碰到一個問題的時候,才發現自己是真的傻逼了,具體問題的應用場景就不在這裡說了,下面我將簡單舉例說明下; 示例1: var a=20; function b1(){ console.log(a); }; function b2(){ var a=40; b1(); }; b2(); 如果能夠正確的寫出最後的結果的朋友們請忽略本題,如果和我一樣,想象的結果和實際的執行結果不一致的話,那麼請接著往下看。 對於上面的題目,我自己一開始沒咋經過大腦,或者說經過了大腦,但是基於對作用域和作用域鏈的理解不是那麼的深刻,所以做錯了這題。 上面的示例中,首先是經過全域性作用域,這個相信大家應該沒什麼問題, 然後在全域性作用域中,先進行預解析,此時會有一個變數物件,該變數物件中有a屬性和b1,b2宣告的函式。之後程式碼開始進入到執行步驟,在執行步驟中,遇到了a變數賦值以及執行函式b2,此時控制器進入到了b2的函式作用域中, 同樣,先進行預解析,此時變數函式中會有變數a,然後在進入到程式碼執行階段,在程式碼執行階段,遇到了可執行程式碼b1();則進入到函式b1中, 進入到b1中時,遇到了console.log(a)了,那麼首先在函式b1中找變數a,此時會發現沒有變數a,那麼,將在函式b1的父作用域中找變數a,而函式b1的父作用域是全域性作用域,在全域性作用域中, 找到了a=20;則此時最後的輸出結果是20;所以經過示例1我們可以看到, 函式的作用域是定義的時候就已經確定了,而不是在呼叫的時候確定的

以上就是一個大致的思路了,下面請大家繼續看下一個示例: var a=20; function b1(){ console.log(this.a); }; function b2(){ this.a=40; b1(); }; b2(); 同理,非常瞭解作用域和作用域鏈以及this指向的同學請路過即好,那麼上面的程式碼最終的輸出結果是什麼呢?原因是什麼。 如果此時看了第一個示例解釋的同學可能會說,答案是20;那不是和第一題一樣嘛,那麼恭喜你,同學,成功答錯了,為什麼呢? 在上面的示例中, 正常的作用域是和示例1一樣的,但是這裡又涉及到了另外一個點,es5中this的指向性問題,這裡就不針對this的指向性做詳細的解釋了,關於this的指向問題的話,有一個結論就是,this的確定是在函式執行時候確定的
。可能有的同學會比較迷糊了,那麼我們還是針對示例2來看: 在示例2中,b1函式是呼叫了this.a,而this的指向又是在b1呼叫的時候確定的,所以我們需要到b2中去看了,在b2中指向b1的時候,此時this才有了一個真正的指向物件了,在這裡,此時b1中的this指向的是b2,那麼很顯然,既然指向b2,那麼this.a也就是指向了b2中的a了, 所以最後的結果就是40 個人的描述能力比較差,如果有什麼描述不清楚的地方,歡迎來噴。