閉包的存儲
① JavaScript中的閉包是用來做什麼的
閉包有兩個作用,一是外部可以讀取函數內部的變數
functionf1(){
n=999;
functionf2(){
alert(n);
}
returnf2;
}
varresult=f1();
result();//999
另一個就是讓這些變數的值始終保持在內存中
functionf1(){
varn=999;
nAdd=function(){n+=1}
functionf2(){
alert(n);
}
returnf2;
}
varresult=f1();
result();//999
nAdd();
result();//1000
在這段代碼中,result實際上就是閉包f2函數。它一共運行了兩次,第一次的值是999,第二次的值是1000。這證明了,函數f1中的局部變數n一直保存在內存中,並沒有在f1調用後被自動清除。
為什麼會這樣呢?原因就在於f1是f2的父函數,而f2被賦給了一個全局變數,這導致f2始終在內存中,而f2的存在依賴於f1,因此f1也始終在內存中,不會在調用結束後,被垃圾回收機制(garbage collection)回收。
這段代碼中另一個值得注意的地方,就是「nAdd=function(){n+=1}」這一行,首先在nAdd前面沒有使用var關鍵字,因此 nAdd是一個全局變數,而不是局部變數。其次,nAdd的值是一個匿名函數(anonymous function),而這個
匿名函數本身也是一個閉包,所以nAdd相當於是一個setter,可以在函數外部對函數內部的局部變數進行操作。
其應用場景就是:
函數a中i只有函數b才能訪問,而無法通過其他途徑訪問到,因此保護了i的安全性。
在內存中維持一個變數
通過保護變數的安全實現JS私有屬性和私有方法(不能被外部訪問)
私有屬性和方法在Constructor外是無法被訪問的
② 怎樣理解「閉包」
閉包是可以包含自由(未綁定)變數的代碼塊;這些變數不是在這個代碼塊或者任何全局上下文中定義的,而是在定義代碼塊的環境中定義。「閉包」 一詞來源於以下兩者的結合:要執行的代碼塊(由於自由變數的存在,相關變數引用沒有釋放)和為自由變數提供綁定的計算環境(作用域)。在 Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby 和 Python 等語言中都能找到對閉包不同程度的支持。
閉包的價值在於可以作為函數對象 或者匿名函數,對於類型系統而言這就意味著不僅要表示數據還要表示代碼。支持閉包的多數語言都將函數作為第一級對象,就是說這些函數可以存儲到變數中、作為參數傳遞給其他函數,最重要的是能夠被函數動態地創建和返回。
③ 閉包是用來做什麼的(js)
閉包是指有權訪問另外一個函數作用域中的變數的函數。
閉包就是函數的局部變數集合,只是這些局部變數在函數返回後會繼續存在。閉包就是就是函數的「堆棧」在函數返回後並不釋放,我們也可以理解為這些函數堆棧並不在棧上分配而是在堆上分配。當在一個函數內定義另外一個函數就會產生閉包。
作用是:匿名自執行函數:我們知道所有的變數,如果不加上var關鍵字,則默認的會添加到全局對象的屬性上去,這樣的臨時變數加入全局對象有很多壞處,如:別的函數可能誤用這些變數;造成全局對象過於龐大,影響訪問速度(因為變數的取值是需要從原型鏈上遍歷的)。除了每次使用變數都是用var關鍵字外,我們在實際情況下經常遇到這樣一種情況,即有的函數只需要執行一次,其內部變數無需維護,可以用閉包。
結果緩存:我們開發中會碰到很多情況,設想我們有一個處理過程很耗時的函數對象,每次調用都會花費很長時間,那麼我們就需要將計算出來的值存儲起來,當調用這個函數的時候,首先在緩存中查找,如果找不到,則進行計算,然後更新緩存並返回值,如果找到了,直接返回查找到的值即可。閉包正是可以做到這一點,因為它不會釋放外部的引用,從而函數內部的值可以得以保留。
④ swift 什麼情況下使用閉包
閉包是功能性自包含模塊,可以在代碼中被傳遞和使用。 Swift 中的閉包與 C 和 Objective-C中的 blocks 以及其他一些編程語言中的 lambdas 比較相似。
閉包可以 捕獲 和存儲其所在上下文中任意常量和變數的引用。 這就是所謂的閉合並包裹著這些常量和變數,俗稱閉包。Swift會為您管理在 捕獲 過程中涉及到的內存操作。
注意:如果您不熟悉 捕獲 (capturing) 這個概念也不用擔心,後面會詳細對其進行介紹。
在Swift函數章節中介紹的全局和嵌套函數實際上也是特殊的閉包,閉包採取如下三種形式之一:
全局函數是一個有名字但不會捕獲任何值的閉包
嵌套函數是一個有名字並可以捕獲其封閉函數域內值的閉包
閉包表達式是一個利用輕量級語法所寫的可以捕獲其上下文中變數或常量值的沒有名字的閉包
Swift的閉包表達式擁有簡潔的風格,並鼓勵在常見場景中以實現語法優化,主要優化如下:
利用上下文推斷參數和返回值類型
單表達式(single-expression)閉包可以省略 return 關鍵字
參數名稱簡寫
Trailing 閉包語法
⑤ php如何序列化/存儲閉包(Closure)
實在需要序列化,可以用反射(Reflection),並直接操作代碼文件獲得上下文信息:/*** 創建一個反射:*/$reflection = new ReflectionFunction($closure);/*** 參數可以直接得到了:*/$params = $reflection-getParameters();/*** 獲得Closure的函數體和use變數,形如: * function($arg1, $arg2, ...) use ($val1, $val2, ...) { * // 要獲得這個部分的代碼!* }* 辦法很多,你可以直接用正則、字元串查找或者Tokenizer,等等等等。 * 比如可以先從reflection里得到函數的開始行和結束行:*/$startLine = $reflection-getStartLine(); $endLine = $reflection-getEndLine(); // 然後用str*這個,str*那個的函數來清理,細節不寫了:
⑥ 為什麼JavaScript閉包能保存變數在內存中
因為返回了一個內部引用,這個內部引用又引用了變數,所以變數在內存中,如
function a(){
var i = 0;
function b(){
alert(i++);
}
return b;
}
var c = a();
c();
c();
手寫的代碼,不保證正確