摘要:在作用域鏈中,外部函數(shù)的活動對象始終處于第二位,外部函數(shù)的外部函數(shù)的活動對象處于第三位,直到作用域鏈終點即全局執(zhí)行環(huán)境。更為重要的是函數(shù)在執(zhí)行完畢后,其他活動對象也不會被銷毀,因為匿名函數(shù)的作用域鏈仍然在引用這個活動對象。
原文鏈接----請點這里
知識儲備??閉包是指有權訪問另一個函數(shù)作用域中的變量的函數(shù),創(chuàng)建閉包的常見方式,就是在一個函數(shù)內(nèi)部創(chuàng)建另一個函數(shù)。
??之所以一個內(nèi)部的函數(shù)可以訪問其外部的變量,而且在其被返回或是調(diào)用時還可以訪問,是因為這個內(nèi)部函數(shù)的作用域鏈中包含外部函數(shù)的作用域。
在了解閉包之前,先要熟悉以下幾點:
??1. 首先要理解執(zhí)行環(huán)境,執(zhí)行環(huán)境定義了變量或函數(shù)有權訪問的其他數(shù)據(jù)。
??2. 每個執(zhí)行環(huán)境都有一個與之關聯(lián)的變量對象,環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中。
??3. 每個函數(shù)都有自己的執(zhí)行環(huán)境,當執(zhí)行流進入一個函數(shù)時,函數(shù)的環(huán)境就會被推入到一個環(huán)境棧中。而在函數(shù)執(zhí)行之后,棧將其環(huán)境彈出,把控制權返回給之前的執(zhí)行環(huán)境。
??4. 當某個函數(shù)被調(diào)用時,會創(chuàng)建一個執(zhí)行環(huán)境及其相應的作用域鏈。然后使用arguments和其他命名參數(shù)的值來初始化函數(shù)的活動對象。在函數(shù)中,活動對象作為變量對象使用(作用域鏈是由每層的變量對象鏈起來的)。
??5. 在作用域鏈中,外部函數(shù)的活動對象始終處于第二位,外部函數(shù)的外部函數(shù)的活動對象處于第三位,直到作用域鏈終點即全局執(zhí)行環(huán)境。
??6. 作用域鏈的本質(zhì)是一個指向變量對象的指針列表,它只引用但不實際包含變量對象。
??不談論閉包,一般的,從在全局執(zhí)行環(huán)境創(chuàng)建一個函數(shù)開始。
??在創(chuàng)建一個函數(shù)時,會創(chuàng)建一個預先包含全局變量對象的作用域鏈,這個作用域鏈被保存在函數(shù)內(nèi)部的[[Scope]]。
??然后執(zhí)行流進入這個函數(shù),函數(shù)的執(zhí)行環(huán)境被壓入環(huán)境棧中,此函數(shù)執(zhí)行環(huán)境的活動對象作為變量對象被創(chuàng)建并推入執(zhí)行環(huán)境作用域鏈的前端。
??對這個例子中的函數(shù)而言,其作用域鏈中包含兩個變量對象:本地活動對象和全局變量對象。
??無論在什么時候在函數(shù)中訪問變量時,會從作用域鏈搜索變量名。
??一般情況下,函數(shù)執(zhí)行完,局部活動對象就會被銷毀,內(nèi)存中僅有全局作用域(里邊只有全局執(zhí)行環(huán)境的變量對象)。
??以下面這段代碼為例:
function compare (value1, value2) { //創(chuàng)建一個預先包含全局變量對象的作用域鏈,保存在[[Scope]] if (value1 < value2) { //訪問函數(shù)變量時,即在代碼最后一條語句執(zhí)行過程中,會從作用域鏈前端開始搜索變量名 return -1; } else if (value1 > value2) { return 1; } else { return 0; } } var result = compare(5, 10); //執(zhí)行流進入函數(shù)時,compare的執(zhí)行環(huán)境壓入環(huán)境棧 //compare執(zhí)行環(huán)境的活動對象作為變量對象接到作用域鏈的前端 //函數(shù)執(zhí)行完,compare執(zhí)行環(huán)境彈出棧,compare活動對象銷毀
如圖,作用域鏈從0開始向后查找:
如下是一個以屬性名作為參數(shù),按其屬性的值對數(shù)據(jù)進行排序的函數(shù):
function createComparisonFunction(propertyName) { return function(object1,object2){ //返回一個匿名函數(shù) var value1=object1[propertyName]; var value2=object2[propertyName]; if(value1value2){ return 1; } else { return 0; } }; } var data=[{name:"Zachary",age:28},{name:"Nicholas",age:29}]; data.sort(createComparisonFunction("name")); console.log(data[0]); //Object {name: "Nicholas", age: 29} data.sort(createComparisonFunction("age")); console.log(data[0]); //Object {name: "Zachary", age: 28}
createComparisonFunction()函數(shù)和返回的匿名函數(shù)的作用域鏈如下圖所示:
??在匿名函數(shù)從createComparisonFunction()中被返回后,它的作用域鏈被初始化為包含createComparisonFunction()函數(shù)的活動對象和全局變量對象。這樣,匿名函數(shù)就可以訪問在createComparisonFunction()中定義的所有變量。
更為重要的是:
??createComparisonFunction()函數(shù)在執(zhí)行完畢后,其他活動對象也不會被銷毀,因為匿名函數(shù)的作用域鏈仍然在引用這個活動對象。
??當createComparisonFunction()函數(shù)返回后,其執(zhí)行環(huán)境的作用域鏈會被銷毀,但它的活動對象仍然會留在內(nèi)存中;直到匿名函數(shù)被銷毀,createComparisonFunction()的活動對象才會被銷毀。
??例如以下代碼,返回的匿名函數(shù)被保存在變量compareNames中,通過將compareNames設置為null來解除對匿名函數(shù)的引用,解除引用之后垃圾回收例程將會清除該匿名函數(shù),隨之該匿名函數(shù)的作用域鏈也會被銷毀,則其作用域鏈上的其他作用域也會安全的銷毀(全局作用域除外)。
var compareNames = createComparisonFunction("name"); var result = compareNames({ name: "Nicholas" }, { name: "Greg" }); compareNames = null;
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87055.html
摘要:閉包解決的問題獲取到函數(shù)內(nèi)部的變量讓變量不會隨著函數(shù)執(zhí)行完畢就銷毀而是保存在內(nèi)存中模擬私有變量閉包產(chǎn)生的問題容易造成內(nèi)存泄漏,保存的多了,卻沒有釋放的指向問題,在閉包里,指向的是關于閉包的小東西比如注釋部分省了外殼, 閉包概念:能夠訪問另一個函數(shù)作用域的變量的函數(shù),來個栗子 showImg(https://segmentfault.com/img/bVbvnmY?w=604&h=245...
摘要:在此例中,在匿名函數(shù)被返回后,它的作用域鏈初始化為包含函數(shù)的活動對象和全局變量對象。函數(shù)在執(zhí)行完畢后,其活動對象也不會被銷毀,因為匿名函數(shù)的作用域鏈仍然在引用這個活動對象,結(jié)果就是只是的執(zhí)行環(huán)境的作用域鏈會被銷毀,其活動對象會留在內(nèi)存中。 寫在前面 注:這個系列是本人對js知識的一些梳理,其中不少內(nèi)容來自書籍:Javascript高級程序設計第三版和JavaScript權威指南第六版,...
摘要:大名鼎鼎的閉包面試必問。閉包的作用是什么??吹介]包在哪了嗎閉包到底是什么五年前,我也被這個問題困擾,于是去搜了并總結(jié)下來。關于閉包的謠言閉包會造成內(nèi)存泄露錯。閉包里面的變量明明就是我們需要的變量,憑什么說是內(nèi)存泄露這個謠言是如何來的因為。 本文為饑人谷講師方方原創(chuàng)文章,首發(fā)于 前端學習指南。 大名鼎鼎的閉包!面試必問。請用自己的話簡述 什么是「閉包」。 「閉包」的作用是什么。 首先...
摘要:相像閉包和對象之間的關系可能不是那么明顯。一個沒有對象的編程語言可以用閉包來模擬對象。事實上,表達一個對象為閉包形式,或閉包為對象形式是相當簡單的。簡而言之,閉包和對象是狀態(tài)的同構(gòu)表示及其相關功能。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌著滬江血液的純粹工程:認真,...
閱讀 2784·2021-09-02 15:11
閱讀 937·2019-08-26 18:18
閱讀 1899·2019-08-26 11:57
閱讀 3350·2019-08-23 16:59
閱讀 2024·2019-08-23 16:51
閱讀 2335·2019-08-23 16:11
閱讀 3168·2019-08-23 14:58
閱讀 1134·2019-08-23 11:34