python闭包的原理_web前端:js 闭包原理
閉包包含自由(未綁定到特定對象)變量;這些變量不是在這個代碼塊內或者任何全局上下文中定義的,而是在定義代碼塊的環(huán)境中定義(局部變量)。"閉包"一詞來源于以下兩者的結合:要執(zhí)行的代碼塊(由于自由變量被包含在代碼塊中,這些自由變量以及它們引用的對象沒有被釋放)和為自由變量提供綁定的計算環(huán)境(作用域)。
閉包的定義:閉包是指有權訪問另一個函數(shù)作用域中的變量的函數(shù)--《Javascript高級程序設計》。
如何理解這句話:其實就是指在函數(shù)a外面能夠訪問函數(shù)a里面的函數(shù)b。
例如:
functiona(){
varv=123;
functionb(){
console.log(v);
}
returnb;
}
varb=a();
b();//123
執(zhí)行函數(shù)a時把函數(shù)b返回,此時函數(shù)b就保存到了a的外面,這時候就可以在a函數(shù)的外部對b進行訪問。
相關知識點:js作用域鏈
執(zhí)行原理:
1、首先在預編譯全局代碼時,生成GO
GO{
a:functiona(){...},
b:undefined
}
2、執(zhí)行varb=a();此時對a函數(shù)進行預編譯并創(chuàng)建a函數(shù)的AO
AO{
v:undefined,
a:undefined,
b:functionb(){...}
}
3、創(chuàng)建a函數(shù)的作用域鏈
a.[[Scopes]]=[AO,GO];
4、由于函數(shù)的提升,會在a函數(shù)進行預編譯的時候創(chuàng)建b函數(shù)的AO
bAO{}
b.[[Scopes]]=[AO(b),AO(a),GO]
5、執(zhí)行varv=123;在js預編譯中提到由于varv的聲明已經(jīng)得到了提升,所以此時只執(zhí)行v=123;對AO里的v進行賦值。
AO{
v:123,
a:undefined,
b:functionb(){...}
}
6、之后將函數(shù)b返回,此時a函數(shù)執(zhí)行完畢,a函數(shù)對應的AO理應銷毀,但是由于在b函數(shù)中又對a函數(shù)的AO中的變量進行應用,所以a函數(shù)的AO不能被垃圾回收機制銷毀,但是會跟a函數(shù)斷開聯(lián)系,當a函數(shù)再次執(zhí)行,會重新創(chuàng)建一個a函數(shù)的AO。
7、在全局變量中使用b接收函數(shù)a的返回,此時GO變?yōu)?/p>
GO{
a:functiona(){...},
b:functionb(){...}
}
8、全局里的b
在b函數(shù)中打印v變量,由于b函數(shù)的AO中沒有v變量,所以順著作用域鏈往上找,在a的AO中找到v并打印。
閉包優(yōu)缺點:
優(yōu)點:
1、屬性的私有化,在b返回后,處理b函數(shù)中能對v進行操作,其它地方都不能對v進行操作。
2、防止變量污染。
缺點:
容易造成內存泄漏,因為如果后期不對全局中的b進行處理(例如:賦值為null),a函數(shù)的AO會一直存在于內存中,如果多次調用a函數(shù),容易導致內存中的垃圾數(shù)據(jù)越來越多造成內存泄漏。
在php、Scala、Scheme、CommonLisp、Smalltalk、Groovy、JavaScript、Ruby、Python、Go、Lua、objectivec、Swift以及java(Java8及以上)等語言中都能找到對閉包不同程度的支持。
總結
以上是生活随笔為你收集整理的python闭包的原理_web前端:js 闭包原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 以下描述中不属于python语言控制结构
- 下一篇: websocket python爬虫_p