92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线

JavaScript作用域和閉包

2021-9-14    前端達人


前言

深入了解閉包和作用域鏈就需先了解函數預編譯的過程


一、預編譯

JavaScript:運行三部曲:
語法分析–預編譯–解釋執行
預編譯:
發生在函數執行的前一刻。
函數聲明整體提升,變量只聲明提升。
1.函數預編譯的過程:
1.創建AO對象Activation Object(執行期上下文,其作用就是我們理解的作用域,函數產生的執行空間庫)
2.找形參和變量聲明,將變量和形參名作為AO屬性名,值為undefined
3.將實參值與形參統一
4.找到函數聲明,將函數名作為屬性名,值為函數體。
例:

function test (a, b){ console.log(a); c = 0; var c; a = 3; b = 2; console.log(b); function b (){}; function d (){}; console.log(b); } test(1); /*答案:1,2,2
答題過程:找形參和變量聲明,將變量和形參名作為 AO 屬性名,值為 undefined, AO{
 a : 1,
 b : undefined,
 c : undefined
}
函數聲明 function b(){}和 function d(){},AO{
 a : 1,
 b : function b(){},
 c : undefined,
 d : function d(){}
}
執行 console.log(a);答案是 1
執行 c = 0;變 AO{
 a : 1,
 b : function b(){},
 c : 0,
 d : function d(){}
}
var c 不用管,因為 c 已經在 AO 里面了
執行 a = 3;改 AO{
 a : 3,
 b : function b(){},
 c : 0,
 d : function d(){}
}
執行 b = 2;改 AO{
 a : 3,
 b : 2,
 c : 0,
 d : function d(){}
}
執行 console.log(b);答案是 2
function b () {}和 function d(){}已經提過了,不用管
執行 console.log(b);答案是 2*/ 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

2.全局預編譯它和函數預編譯步驟一樣,但它創造的是GO(全局對象):
1.生成了一個 GO 的對象 Global Object(window 就是 GO
2.找變量聲明…
3.找函數聲明…

任何全局變量都是 window 上的屬性
變量沒有聲明就賦值了,歸 window 所有,就是在 GO 里面預編譯。
例 :

function test(){ var a = b =123; console.log(window.b); } test(); 答案 a 是 undefined,b 是 123 先生成 GO{ b : 123 } 再有 AO{ a : undefined } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

想執行全局,先生成 GO,在執行 test 的前一刻生成 AO
函數里找變量,因為GO和AO有幾層嵌套關系,近的優先,從近的到遠的, AO里有就看 AO,AO 沒有才看 GO。所以函數局部變量和全局變量同名,函數內只會用局部。

二、作用域精講

作用域定義:變量(變量作用于又稱上下文)和函數生效(能被訪問)的區域
全局、局部變量
作用域的訪問順序:函數外面不能用函數里面的。里面的可以訪問外面的,外面的不能訪問里面的,彼此獨立的區間不能相互訪問。

1.[[scope]]: 每個 javascript 函數都是一個對象,對象中有些屬性我們可以訪問,但有些不可以,這些屬性僅供 javascript 引擎存取,[[scope]]就是其中一個。[[scope]]指的就是我們所說的作用域,其中存儲了運行期上下文的集合。

2.執行期上下文: 當函數在執行的前一刻,會創建一個稱為執行期上下文的內部對象(AO)。
一個執行期上下文定義了一個函數執行時的環境,函數每次執行時對應的執行上下文都是獨一無二的,所以多次調用一個函數會導致創建多個執行上下文,當函數執行完畢,執行上下文被銷毀。

3.作用域鏈:[[scope]]中所存儲的執行期上下文對象的集合(GO和AO),這個集合呈鏈式鏈接,我們把這種鏈式鏈接叫做作用域鏈。

4.查找變量: 在哪個函數里面查找變量,就從哪個函數作用域鏈的頂端依次向下查找(先查自己的AO,再查父級的AO,一直到最后的GO)。
函數類對象,我們能訪問 test.name
test.[[scope]]隱式屬性——作用域

作用域鏈圖解:

function a (){ function b (){ var bb = 234; aa = 0; } var aa = 123; b(); console.log(aa) } var glob = 100; a(); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

0 是最頂端,1 是次頂端,查找順序是從最頂端往下查
在這里插入圖片描述
在全局預編譯中函數a定義時,它的[[scope]]屬性中有GO對象。
在這里插入圖片描述
在函數a執行前先函數預編譯,創建自己的AO對象,并存儲在[[scope]]屬性上,與之前存儲的GO成鏈式。同時函數b被創建定義。
在這里插入圖片描述
在b被創建時,它生成的[[scope]]屬性直接存儲了父級的[[scope]],它有了父級的AO和GO。
在這里插入圖片描述
b函數執行前預編譯,生成自己的AO,存儲在[[scope]]屬性中。

詳解過程: 注意[[scope]]它是數組,存儲的都是引用值。
b 中 a 的 AO 與 a 的 AO,就是同一個 AO,b 只是引用了 a 的 AO,GO 也都是同一個。
function b(){}執行完,干掉的是 b 自己的 AO(銷毀執行期上下文)(去掉連接線),下次 function b 被執行時,產生的是新的 b 的 AO。b 執行完只會銷毀自己的 AO,不會銷毀 a 的 AO。會退回到b被定義時(仍有父級的AO和GO)。
function a(){}執行完,會把 a 自己的 AO 銷毀【也會把 function b的[[scope]]也銷毀】,只剩 GO(回歸到 a 被定義的時候),等下次 function a再次被執行時,會產生一個全新的 AO,里面有一個新的 b 函數。。。。。。周而復始。

思考一個問題:如果 function a 不被執行,下面的 function b 和 function c 都是看不到的(也不會被執行,被折疊)。只有 function a 被執行,才能執行 function a 里面的內容a();不執行,根本看不到 function a (){}里面的內容,但我們想在a函數外面調用b函數怎么辦呢,于是閉包出現了。

三、閉包

閉包的定義

當內部函數被保存到外部時,將會生成閉包。但凡是內部的函數被保存到外部,一定生成閉包。
閉包的問題:閉包會導致原有作用域鏈不釋放,作用域中的局部變量一直被使用著,導致該作用域釋放不掉,造成內存泄露(就是占有過多內存,導致內存越來越少,就像泄露了一樣)
例:

function a(){ function b(){ var b=456; console.log(a); console.log(b); } var a=123; return b; } var glob = a(); glob(); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

答案 123,456。
function a(){ }是在 return b 之后才執行完,才銷毀。而return b 把 b(包括 a 的 AO)保存到外部了(放在全局)當 a 執行完砍掉自己的 AO 時(砍掉對AO存儲地址的指針),因為b還保存著對a的AO的引用,所以內存清除機制不會清除掉a的AO, b 依然可以訪問到 a 的 AO。

閉包的作用:

1.實現共有變量

function test(){ var num=100; function a(){ num++; } function b(){ num--; } return [a,b]; } var myArr=test(); myArr[0](); myArr[1](); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

答案 101 和 100。
思考過程:說明兩個用的是一個 AO。
myArr[0]是數組第一位的意思,即 a,myArr0;就是執行函數 a 的意思;
myArr[1]是數組第二位的意思,即 b,myArr1; 就是執行函數 b 的意思。
test doing test[[scope]] 0:testAO
1:GO
a defined a.[[scope]] 0 : testAO
1 : GO
b defined b.[[scope]] 0 : testAO
1 : GO
return[a, b]將 a 和 b 同時被定義的狀態被保存出來了
當執行 myArr0;時
a doing a.[[scope]] 0 : aAO
1 : testAO
2 : GO
當執行 myArr1;時
b doing b.[[scope]] 0 : bAO
1 : a 運行后的 testAO
2 : GO
a 運行后的 testAO, 與 a doing 里面的 testAO 一模一樣
a 和 b 連線的都是 test 環境,對應的一個閉包

2.可以做緩存(存儲結構)

function eater(){ var food=""; var obj={ eat : function (myFood){ console.log("i am eating"+food); food =""; }, push : function (myFood){ food = myFood; } } return obj; } var eater1 = eater(); eater1.push("banana"); eater1.eat(); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

答案 i am eating banana,eat 和 push 操作的是同一個 food
在 function eater(){里面的 food}就相當于一個隱式存儲的機構
obj 對象里面是可以有 function 方法的,也可以有屬性,方法就是函數的表現形式

3.可以實現封裝,屬性私有化
只能調用函數方法,不能修改函數的屬性。

4.模塊化開發,防止污染全局變量


























藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

分享此文一切功德,皆悉回向給文章原作者及眾讀者.

轉自:csdn
免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

藍藍設計m.skdbbs.com )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

日歷

鏈接

個人資料

藍藍設計的小編 http://m.skdbbs.com

存檔

92国产精品视频_亚洲a级在线观看_国产精品电影观看_国产精品免费观看在线_精品伊人久久97_亚洲人成在线观_尤物九九久久国产精品的特点_成人激情在线播放_成人黄色大片在线免费观看_亚洲成人精品久久久_久久免费视频在线观看_久久精品国产一区_国产一区二区三区18_亚洲欧美中文字幕在线一区_日韩美女中文字幕_日韩视频免费在线
91偷拍一区二区三区精品| 麻豆一区二区三| 99免在线观看免费视频高清| 国产三级精品在线| 日韩二区三区在线观看| 一区二区三区色| 337p日本欧洲亚洲大胆色噜噜| 日韩脚交footjobhd| 蜜桃av色综合| 色94色欧美sute亚洲13| 日韩久久精品电影| 日韩欧美精品免费在线| 91精品国产99久久久久久| 久久精品视频导航| 欧美www视频在线观看| jizz在线免费观看| 精品精品国产高清a毛片牛牛| 午夜日韩成人影院| 性亚洲最疯狂xxxx高清| 亚洲小说图片| 国产一区二区伦理片| 久久一区欧美| 欧美日韩mv| 欧美理论一区二区| 91精品福利在线一区二区三区| 日韩暖暖在线视频| 精品freesex老太交| 日韩中文字幕无砖| 青青草国产精品亚洲专区无| 欧美亚洲午夜视频在线观看| 欧美最猛性xxxxx(亚洲精品)| 久久婷婷蜜乳一本欲蜜臀| 亲子伦视频一区二区三区| 日日噜噜噜噜夜夜爽亚洲精品| 久久先锋影音av| 午夜不卡一区| 欧美高清视频在线高清观看mv色露露十八| 成人伊人精品色xxxx视频| 国产精品久久久久久久第一福利| 欧美日韩国产在线播放网站| 亚洲一区二区久久久久久| 欧美在线观看18| 久久久久久久久久av| 欧美色欧美亚洲高清在线视频| 欧美在线首页| 最近中文字幕mv在线一区二区三区四区| 亚洲欧美一区二区精品久久久| 波多野结衣在线观看| 欧美视频二区| 欧美肥老太太性生活| 久久在线视频免费观看| av中文字幕一区二区| 97久久超碰精品国产| 国产精品一区二区不卡视频| 日本不卡的三区四区五区| 日韩成人高清| 成人免费看视频网站| sm国产在线调教视频| 在线免费观看的av网站| 久久九九热re6这里有精品| 国产一区二区不卡| 国产成人极品视频| 亚洲欧美日韩国产中文在线| 国产精品av一区二区| 亚洲综合在线五月| 欧美日韩视频在线播放| 亚洲色图88| 日韩亚洲成人av在线| www.一区二区| 欧美电影免费提供在线观看| 一色屋精品亚洲香蕉网站| 中文字幕在线中文字幕在线中三区| 国产91在线播放| 久久91精品国产91久久久| 久久久精品天堂| 日韩成人中文电影| www.66久久| 夜夜嗨av色综合久久久综合网| 国产精品视频观看| 国产夜色精品一区二区av| 日本国产精品| xvideos亚洲人网站| 欧美日韩中文| 粉嫩老牛aⅴ一区二区三区| 欧洲亚洲精品在线| 欧美伊人久久久久久久久影院| 婷婷亚洲久悠悠色悠在线播放| 国产自产女人91一区在线观看| 日韩视频中午一区| 好吊妞国产欧美日韩免费观看网站| 国产精品久久久久久久久久妞妞| 亚洲国产另类 国产精品国产免费| 岛国精品在线观看| 色婷婷综合网| 欧美日韩电影在线观看| 国内激情视频在线观看| 国产盗摄精品一区二区酒店| 精品国产三级a在线观看| 国产美女精品久久久| 成人羞羞动漫| 欧美日本亚洲视频| 欧美午夜在线播放| 麻豆乱码国产一区二区三区| 国产精品极品美女在线观看免费| 日本不卡一二三区黄网| 亚洲精品在线91| 亚洲天堂2016| 亚洲免费观看高清| 久久精品99国产国产精| 欧美经典影片视频网站| 99久久99久久精品国产片果冰| 国产精品久久国产愉拍| 久久视频社区| 久久国产主播精品| 欧美成人久久久| 国产精品久久久999| 精品国产乱码91久久久久久网站| 成人午夜在线播放| 日韩亚洲成人av在线| 日本韩国在线视频爽| 欧美顶级少妇做爰| 久久久久久日产精品| 亚洲一区二区三区三| 国产成人精品日本亚洲专区61| 国产成人一区二| 欧美黄色a视频| 精品日本一区二区| 久久久久美女| 久久九九国产| 黄色网一区二区| 99成人在线视频| 91久久国产综合久久91精品网站| 成人精品免费视频| 日本一区高清不卡| 日本在线免费看| 亚洲1区2区3区视频| 色婷婷综合久久| 综合网日日天干夜夜久久| 夜夜精品视频一区二区| 日韩精品小视频| 91av在线播放| 老司机免费视频一区二区三区| 好操啊在线观看免费视频| 日韩免费电影一区二区三区| 一区二区电影在线观看| 欧美性理论片在线观看片免费| 久久综合久色欧美综合狠狠| 精品人伦一区二区三区蜜桃网站| 91蝌蚪porny| 超碰个人在线| 国产69精品久久久久9999apgf| 久久精品午夜一区二区福利| 亚洲欧洲日韩一区二区三区| 日韩一区二区免费电影| 日本久久成人网| 国产精品日日摸夜夜添夜夜av| 最新国产精品视频| 成人做爰视频www网站小优视频| www.欧美色图| 欧美亚洲三区| 成人一级毛片| 91久久国产综合久久91精品网站| av片哪里在线观看| 欧美一区二区久久久|