Javascript和Java中閉包的理解
一。Javascript中閉包:
1.變數的作用域
要理解閉包,首先必須理解Javascript特殊的變數作用域。變數的作用域無非就是兩種:全域性變數和區域性變數。
Javascript語言的特殊之處,就在於函式內部可以直接讀取全域性變數
var n=999;
function f1(){
alert(n);
}
f1(); // 999
另一方面,在函式外部自然無法讀取函式內的區域性變數。
function f1(){
var n=999;
}
alert(n); // error
這裡有一個地方需要注意,函式內部宣告變數的時候,一定要使用var命令。如果不用的話,你實際上聲明瞭一個全域性變數!
function f1(){ n=999; } f1(); alert(n); // 999
2.如何從外部讀取區域性變數
出於種種原因,我們有時候需要得到函式內的區域性變數。但是,前面已經說過了,正常情況下,這是辦不到的,只有通過變通方法才能實現。那就是在函式的內部,再定義一個函式。
function f1(){
n=999;
function f2(){
alert(n); // 999
}
}
既然f2可以讀取f1中的區域性變數,那麼只要把f2作為返回值,我們不就可以在f1外部讀取它的內部變量了嗎!
function f1(){ n=999; function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999
3.閉包的概念
上面的f2函式,就是閉包。閉包其實就是定義在一個函式內部的函式(因為是子函式所以能夠讀取所在父函式的內部變數)。在本質上,閉包就是將函式內部和函式外部連線起來的一座橋樑。
4.閉包的用途
1.可以讀取函式內部的變數.2.讓這些變數(閉包引用的變數)的值始終保持在記憶體中。
在這段程式碼中,result實際上就是閉包f2函式。它一共運行了兩次,第一次的值是999,第二次的值是1000。這證明了,函式f1中的區域性變數n一直儲存在記憶體中,並沒有在f1呼叫後被自動清除。function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000
為什麼會這樣呢?原因就在於f1是f2的父函式,而f2被賦給了一個全域性變數,這導致f2始終在記憶體中,而f2的存在依賴於f1,因此f1也始終在記憶體中,不會在呼叫結束後,被垃圾回收機制(garbage collection)回收。
這段程式碼中另一個值得注意的地方,就是“nAdd=function(){n+=1}”這一行,首先在nAdd前面沒有使用var關鍵字,因此 nAdd是一個全域性變數,而不是區域性變數。其次,nAdd的值是一個匿名函式(anonymous function),而這個
匿名函式本身也是一個閉包,所以nAdd相當於是一個setter,可以在函式外部對函式內部的區域性變數進行操作。
5.使用閉包的注意點
1.由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包2.閉包會在父函式外部,改變父函式內部變數的值。
6.閉包的應用場景
1、保護函式內的變數安全。以最開始的例子為例,函式a中i只有函式b才能訪問,而無法通過其他途徑訪問到,因此保護了i的安全性。2、在記憶體中維持一個變數。依然如前例,由於閉包,函式a中i的一直存在於記憶體中,因此每次執行c(),都會給i自加1。
二。Java中的閉包
1.java中閉包的定義
定義:閉包能夠將一個方法作為一個變數去儲存,這個方法有能力去訪問所在類的自由變數。Java 語言本身還沒有正式支援閉包,但它卻允許模擬閉包(內部類+介面)。可以使用匿名的內部類來實現閉包。
如何讓這個普通物件能夠訪問所在類的自由變數?內部類。內部類能夠訪問外部類的所有屬性及方法。
隱藏具體實現是內部類的作用之一,如何保證隱藏具體實現的同時還能將閉包傳遞到外部使用?讓內部類實現通用介面,然後將內部類物件向上轉型為介面型別。2.程式碼簡單實現:
public final static String name = "純牛奶";// 名稱
private static int num = 16;// 數量
public Milk() {
System.out.println(name + ":16/每箱");
}
/**
* 閉包
*
* @return 返回一個喝牛奶的動作
*/
public Active HaveMeals() {
return new Active() {
public void drink() {
if (num == 0) {
System.out.println("木有了,都被你丫喝完了.");
return;
}
num--;
System.out.println("喝掉一瓶牛奶");
}
};
}
/**
* 獲取剩餘數量
*/
public void currentNum() {
System.out.println(name + "剩餘:" + num);
}
}
/**
* 通用介面
*/
interface Active {
void drink();
}
//閉包的使用
public class Person {
public static void main(String[] args) {
//買一箱牛奶
Milk m = new Milk();
Active haveMeals = m.HaveMeals();
//沒事喝一瓶
haveMeals.drink();
//有事喝一瓶
haveMeals.drink();
//看看還剩多少?
m.currentNum();
}
}
4.總結:
1.實際專案中沒怎麼用過閉包,因此不能對他的好壞進行評論。2.建議合理的使用閉包,不完全不使用,也不能濫用。
3.特別注意:閉包會導致資源不被回收,如上例,在main方法中將m設為null,使用haveMeals繼續呼叫drink方法仍然會喝掉一瓶牛奶,說明Milk物件並沒有被釋放掉。
相關推薦
Javascript和Java中閉包的理解
一。Javascript中閉包: 1.變數的作用域 要理解閉包,首先必須理解Javascript特殊的變數作用域。 變數的作用域無非就是兩種:全域性變數和區域性變數。 Javascript語言的特殊之處,就在於函式內部可以直接讀取全域性變數 var n=
java 中閉包運用 實現方法傳遞
寫了一個測試java閉包的例項,在事件監聽中用得比較多的設計模式!定義一個介面,通過介面來傳遞方法體/** * @author yaohw * */ public interface Action{ public void excute(Object arg);
JavaScript中閉包實現的私有屬性的getter()和setter()方法
參數 strong prop nbsp body 利用 edi 獲取 展示 註意: 以下的輸出都在瀏覽器的控制臺中 <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g
對JavaScript中閉包的理解
func web瀏覽器 並且 清晰 分享 數量 接下來 我們 回收 相信很多人都有看過關於閉包的文章,但是真正意義上的了解清楚的也不多,今天我們就來談談對閉包的理解。 閉包在JavaScript中一直是一個很重要的存在,閉包很重要但是又很難理解,起初我也是這樣認為,但只要真
JavaScript中閉包的使用和各種繼承介紹
一、什麼是閉包? (1)閉包的概念:a、閉包就是函式巢狀時,讓區域性變數變成自由變數的環境,是一種讓區域性變數進化的方式。 b、定義在一個函式內部的函式。 &
js中的閉包理解
構建 但是 水平 作用 undefined 可能 技術 自身 復制 閉包是一個比較抽象的概念,尤其是對js新手來說.書上的解釋實在是比較晦澀,對我來說也是一樣. 但是他也是js能力提升中無法繞過的一環,幾乎每次面試必問的問題,因為在回答的時候.你的答案的深度,對術語的理
[譯]Javascript中閉包的各種例子
目的 點擊 span 而且 一個 code pre 一件事 播放 本文翻譯youtube上的up主kudvenkat的javascript tutorial播放單 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU&
JAVA中jar包和war包的區別是
服務器 直接 jar文件 tomcat服務 一起 是把 目的 相關 web 其實jar包和war包都可以看成壓縮文件,用解壓軟件都可以打開,jar包和war包所存在的原因是,為了項目的部署和發布,通常把項目打包,通常在打包部署的時候,會在裏面加上部署的相關信息。 這個打包實
javascript中閉包最簡單的簡紹
覆蓋 計數 在一起 com 想要 .com neu 內部 文章 javascript中閉包是什麽 JavaScript 變量可以是局部變量或全局變量。私有變量可以用到閉包。閉包就是將函數內部和函數外部連接起來的一座橋梁。 函數的閉包使用場景:比如我們想要一個函數來執行計數
JavaScript 中 閉包 原理
閉包 引用程式碼片段 //var i=1;//汙染全域性 function fun(){ var i=1; //函式內變數 ao釋放 console.log(i++); } fun();//1 fun();//1 //i=0; 全域性汙染之後變數 會被影響 fun();/
javascript 閉包理解
閉包的含義:閉包就是能夠讀取其他函式內部變數的函式,一個函式內部的函式 閉包的用途: 讀取函式內部的變數;讓這些變數的值始終保持在記憶體中 閉包的弊端:由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大, 所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能
#Java乾貨分享:一篇文章讓你深入瞭解Java中的包和介面
很多新手程式設計師對於Java中兩個具創新性的特徵————包與介面不是非常清楚,所以我特意發了這篇文章來闡述什麼是包,什麼是介面。 包(package)是多個類的容器,它們用於保持類的名稱空間相互隔離。 如果有想學習java的程式設計師,可來我們的java學習扣qun:79979,2590免
JavaScript教程筆記(8)-閉包函式和IIFE
1 閉包 閉包(closure)是JavaScript語言的一大特色,也是一個難點。理解閉包,首先要理解變數作用域。 作用域有兩種:全域性作用域和函式作用域。函式內部可以訪問全域性變數。 var n = 999; function f() { console.log(
javascript閉包理解2
閉包的形成需要兩個條件: 1.在函式內部建立新的函式; 2.新的函式在執行時,訪問了函式的變數物件; 總結一下閉包: 閉包是在函式被呼叫執行的時候才被確認建立的。 閉包的形成,與作用域鏈的訪問順序有直接關係。 只有內部函式訪問了上層作用域鏈中的變數物件時,才會
對Python中閉包的理解
定義 Python閉包表現為:如果在一個內部函式裡,對在外部作用域(非全域性作用域)的變數進行引用,那麼內部函式就被認為是閉包(closure)。 def outer(a): b = 1 def inner(): # 內部函式in
JavaScript閉包理解
什麼是閉包 普通函式中,函式內部可以直接讀取全域性變數,函式外部無法讀取函式內部的區域性變數。 而閉包能夠讀取其他函式內部變數的函式,由於在 Javascript 語言中,只有函式內部的子函式才能讀取區域性變數,因此可以把閉包簡單理解成 “定義在一個函式內部的函式”。所以
關於JavaScript中的date和java中的date差14小時問題
今天遇到一個問題,在java中獲取的時間傳到前臺頁面, 原時間是這樣的:2016-11-10 15:29:11, 傳到前臺來是這樣的:Thu Nov 10 15:29:11 CST 2016, 在js中用getDate(),結果是11,getHours(),結果是5,也就是
java中繼承的理解,super關鍵字,方法的重寫和過載以及注意事項理解
一、類的繼承理解 在java中類的繼承是指:在一個現有類的基礎之上去構建一個新的類,構建出來的新的類被稱為子類,現有類是父類,子類會自動擁有父類所有可繼承的屬性和方法。繼承類是現有類的更具體一些,繼承類可能只擁有一部分父類的屬性和方法。 如圖,這就表示了繼承類是父類的一種更具體形式
Java中Atomic包的原理和分析
原文地址:http://blog.csdn.net/zhangerqing/article/details/43057799 Atomic簡介 Atomic包是Java.util.concurrent下的另一個專門為執行緒安全設計的Java包,包含多個原子操作類。這個
javascript閉包理解之onload事件遍歷獲取陣列元素
我們在學javascript的時候是否遇到過這樣的程式碼,例如我們要在onload事件裡迴圈遍歷一個數組,對遍歷到的陣列元素進行操作。需要用到this物件,如下程式碼所示: onload = fu