文體兩開花 ,說道閉包就必需要說下做用域;說道做用域我就想到了做用域鏈,說道做用域鏈,我就想到了執行期上下文,說道執行期上下文,我就想到了預編譯。因此爲了說下閉包,就得從預編譯提及。(第二次寫文章,文筆不怎麼好,加上內容自己難度挺大,請多多包涵,仔細閱讀,看懂每個字,理解圖片中的每個字)
衆所周知js兩大特色 1.單線程;2.解釋執行(解釋一行,執行一行)。那麼問題來了 以下代碼的輸入結果是什麼?
javascript
console.log(a,b)
function a(){}
var b = 0;複製代碼
解釋一行執行一行, 第一句直接console.log(a,b), 尚未執行到他們的 聲明語句,那結果會不會是 xxx is not defient 。 明顯不是,稍微有點基礎的人都知道 var 和 函數聲明會有提高。 這個提高爲 函數聲明總體提高 , 變量 聲明提高。這個提高的過程就是發生在預編譯。可是預編譯不止這些。
前端
先介紹一波知識點:java
js運行三部曲:對函數:預編譯發生在函數執行前一刻;node
對整js :預編譯發生在全局執行的前一刻;es6
那麼問題來了:函數聲明和變量聲明都提高誰的優先級高呢?面試
看碼:bash
function fn(a) {
console.log(a)
console.log(b)
var a = 123;
console.log(a)
function a(){}
var b = function(){}
console.log(b)
function d (){}
}
fn(1)複製代碼
上面的代碼分別輸出什麼,能夠本身先看看有了答案,再往下看。閉包
在回答上面的問題前先列出 函數預編譯4步曲:函數
全局的預編譯,省略 2.的找形參和 3步的實參和形參統一;
ui
如今來回答上面的問題:
下面給出2個題,而後結束預編譯。(你們能夠先本身坐下,再去本身打下代碼,若是跟本身的答案個控制檯輸出有出入,就看再看看4部曲再作作。熟悉了再往下看喲)
console.log(test);
function test(test) {
console.log(test)
var test = 234;
console.log(test)
function test(){}
}
test(1)
var test = 123;複製代碼
function test (a,b){
console.log(a);
c = 0;
a = 3;
b = 2;
console.log(b);
function b(){}
function d(){}
console.log(b)
}
test(1);複製代碼
來看碼:
function a() {
function b(){
var b = 234;
}
var a = 123;
b();
}
var glob = 100;
a();複製代碼
第二步:a執行,生成了本身的AO,插入到了[[scopes]] 0 位GO 日後延
第三步:a執行引發的b的定義,這個時候b繼承了a的勞動成果,直接把a的生成的做用域鏈的引用拿來掛到本身的身上。這個時候 b.scope[0] 指向的AO和 a.scope[0] 指向的AO是同一個。(結合一下本身寫代碼就能知道,在子函數裏面改變了外部函數的值,外部函數的值也改變了)
第四步:b函數執行,生成了本身的AO,把本身的AO插入到剛剛獲取的做用域鏈
function a (){
function b(){
function c(){
}
c();
}
b();
}
a();複製代碼
看了這個例子,你們應該能明白點了,(如何還沒明白,怪我,第二次寫文章,表達很差) 上面全部的AO和BO 都是一個AO和BO,他們拿到地址指向後就能夠直接用,一個修改所有都被修改。
討論以前,先說一句話,一句開始我加粗了的話 :當函數執行完畢,執行上下文被銷燬
function a () {
function b() {
var bbb = 234;
console.log(aaa)
}
var aaa = 123;
return b;
}
var glob = 100;
var demo = a();
demo();複製代碼
到這裏文體兩開花學閉包就結束了。至於閉包的用處和規避措施。你們就能夠網上搜索了,不少。(如何沒有看懂,是個人問題,文筆太差, 你們多多包涵,有問題歡迎評論區 指出,我看到就會立刻回覆,誰叫我沒工做呢)。
最後祝各位前端攻城師們都能對js瞭如指掌,雖然不少js的一些特性(或者說缺陷)確實噁心,可是說不定哪一天就被觸發了,若是對這些不瞭解,那bug是真的找不到了。
ps:最後的最後打個廣告,本人普通二本軟件工程大四學生,js基礎還行,瞭解一點node,其餘的前段技術也多多少少了解點。正在找一份前端開發的工做,座標成都。但願有找人的大佬,給點內推,面試機會。謝謝大佬們。