Java程式員的JavaScript學習筆記(4——閉包/getter/setter),gettersetter
計劃按如下順序完成這篇筆記:
這是筆記的第4篇,聊聊閉包/getter/setter,看看JavaScript中的變數範圍和實現封裝的方法。
1、閉包
閉包是JavaScript一項簡單實用的語言特性。通過閉包:
彌補了函數沒有public/private等訪問存取權限控制符的缺陷,保護了函數內部變數的安全。
使得函數對象在作為參數傳遞時,不僅僅傳遞運算邏輯,同時也傳遞了相關變數。
使得函數“類”的不同執行個體,獨享自己的屬性。
下面逐個來看。
1.1、保護私人變數1.1.1、原理
閉包最主要的特性是:當函數作為返回值時,連同函數定義時的環境(包括函數外部,函數可以訪問到的變數)一起返回,確保這些變數不因其依附的對象銷毀而被銷毀。
有點兒繞,具體什麼意思呢?看下面的代碼:
// 程式碼片段1
function UiObject() {
var childCount = 0; // 函數內部變數,
return 0;
}
var funcReturnValue = UiObject(); // 調用函數,返回0
console.log(UiObject.childCount); // 輸出:undefined,由於函數調用完成,內部變數已經被銷毀
childCount隨著UiObject函數的調用結束而銷毀,從另一個角度看,保護了函數內部的變數。
在這個基礎上,如果我們有一種辦法可以確保函數的內部變數不被銷毀,而且提供方法對其訪問操作,也就實現了通過public方法訪問 private 變數。
代碼如下:
// 程式碼片段2
function UiObject() {
var childCount = 0; // 函數內部變數
function getChildCount(){
childCount = 6;
return childCount;
}
return getChildCount;
}
var funcReturnFObject = UiObject(); // 調用函數,返回 getChildCount 函數,返回值是一個閉包
console.log(funcReturnFObject()); // 輸出:6
下面我們就看看,如果利用閉包的這一特性實現對私人屬性的保護。
1.1.2、文法
在程式碼片段2的基礎上改進,程式碼片段3展示的代碼,可以同時提供多個方法,對私人屬性訪問。
//程式碼片段3
function UiObject() {
var childCount = 0; // 函數內部變數
return {
getChildCount : function (){
return childCount;
},
setChildCount : function (cnt){
childCount = cnt;
}
};
}
var o = UiObject(); // 調用函數,返回 getChildCount 函數,返回值是一個閉包
o.setChildCount(6);
console.log(o.getChildCount()); // 輸出:6
思考: 如果 var childCount = 0 ; 改為 this.childCount = 0; 呢?
我們之前研究過this,“ this.childCount = 0; ”語句是將childCount附加為調用者的屬性,this.childCount的將生命週期與調用者相同。這與閉包不衝突。
程式碼片段3還可以寫成程式碼片段4的形式。
// 程式碼片段4
function UiObject() {
var childCount = 0; // 函數內部變數
this.setChildCount = function(cnt){
childCount = cnt;
};
this.getChildCount = function(){
return childCount;
};
}
var ui = new UiObject(); // 調用函數,返回retObj
console.log(ui.childCount); // 輸出:undefined,由於函數調用完成,局部變數已經被銷毀
ui.setChildCount(3); // 由於閉包的作用,ui仍然儲存著變數childCount,並對其操作
console.log(ui.getChildCount()); // 輸出:3
“this.setChildCount = function(cnt){ childCount = cnt; };” 這個語句相當於在UiObject內部定義了函數並“傳遞”了給ui對象。同樣產生了閉包。
1.2、傳遞函數時,同時傳遞上下文
通過上面的例子,我們已經看到了這點特性。
在具體的應用情境中可對其大加利用。
1.3、不同執行個體,獨享自己的變數
我們已經知道了,函數在傳遞過程中,會產生一個閉包。對於同一方法產生的閉包,是相同的,還是為每次傳遞建立了不同的拷貝呢?
看下面的代碼:
//程式碼片段5
function UiObject() {
var childCount = 0; // 函數內部變數
return {
getChildCount : function (){
return childCount;
},
setChildCount : function (cnt){
childCount = cnt;
}
};
}
var ui1 = UiObject();
var ui2 = UiObject();
ui1.setChildCount(1);
ui2.setChildCount(2);
console.log(ui1.getChildCount()); // output : 1
console.log(ui2.getChildCount()); // output : 2
每次產生閉包是不同的拷貝。
思考:對比Java,加深理解。
2、getter/setter
JavaScript
//程式碼片段6
var uiPanel ={
_type : 'Panel',
_width : -1,
_height: -1,
get type(){ return this._type;},
get width(){ return this._width; },
set width(v){this._width = v;},
get height(){ return this._height; },
set height(v){this._height = v;}
};
uiPanel.type = 'TextField'; // does not work
console.log('type:'+uiPanel.type); // ouput : type:Panel
uiPanel.width = 800; //
console.log('width:'+uiPanel.width); // ouput : width:800
文法上越發有物件導向的範兒了。
除了在定義時通過set/set關鍵字控制屬性的讀寫權限。還可以在運行期通過 Object.defineProperty()函數動態添加屬性,並提供更精細的控制。
代碼如下(以下代碼均未經實驗):
var o = {};
Object.defineProperty(o,'propName',{
value:1, //屬性的值,也可以通過 get:function(){retun x;}的方法設定
writeable:true,//是否可以通過o.propName = newValue ; 的方法設定屬性的值
enumerable:false,//是否可以通過被枚舉
configurable:true//是否可以通過defineProperty配置
});
另外,還有一系列API可以完成對屬性的配置、檢測。如下:
Object.getOwnPropertyDescriptor{{x:1},"x"}
Object.keys(obj); // 獲得對象上所有可枚舉的“執行個體屬性”
Object.getOwnPropertyNames(obj) ;//獲得對象上所有的“執行個體屬性”
obj.hasOwnProperty(‘id’); //只要該對象obj擁有屬性id, 無論id是否可枚舉,都返回true
3、小結
當大多數人已經習慣了物件導向的思維和方法,語言就要從特性方面予以滿足,這不合理,也不美。但世界就是如此不完美。
JavsScript天生麗質,非要把她改造成機甲戰士,那以後誰來負責傾國傾城呢?
ECMAScript 5不是革命性創新,也不是救命稻草,這個世界本來可以更好的。
JAVA中的setter//getter()方法是什?
用代碼講解一下:
public class Student {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Student s1=new Student();
s1.setName("小明");
System.out.println("學生的姓名為:"+s1.getName());
}
}
上面的意思是建立一個學生類,聲明一個name變數,並給了它getter和setter方法。
先說setter方法,剛開始建立name變數時沒有賦值,後面用這個方法給他賦值“小明”
再說getter方法,name變數有了值“小明”後就可以用這個方法把它調出來。
JAVA程式員需要學習那些課程
多思考 多看老員工的例子 遵守一些編碼規範 包括書寫以及架構規範
學習的知識太多了 javase(java核心技術) jsp(jsp2.0技術手冊) servlet struts(struts in action) spring(spring開發指南)
-----------------------------------------------
我就跟你在這裡說工作上能用的呢。首先你JavaSE的基礎要會,jsp要會寫,並且看得懂,EL最好可以寫一些,jstl基本上我們是不用的,因為有Struts。servlet要求多一點,因為Struts就是Jsp+Servlet的一個進階應用程式。然後你可以學學架構。Struts的結構瞭解就可以,運行以及載入過程要知道,並且在心裡有個數,Spring也一樣,hibrnate一般我們不用,因為項目太大的話優勢體現不出來,小的還可以。練習編寫代碼嚴格按照MVC的規範,嚴禁下層調用上層方法或屬性。在公司我們看的參考書也就是我說的那麼幾本。如果可以ajax最好懂得一些,會很有用。其實在我看來初級的知識就是JavaSE的知識,進階的那些也高不到哪裡去。每個公司都有自己的規範與方法,設計能輪到你就上,輪不到你你就老老實實的寫,設計模式在你參與設計的時候用的上。