javascript
Java程序猿JavaScript学习笔记(4——关闭/getter/setter)
計劃和完成這個例子中,音符的順序如下:
這是筆記的第4篇,聊聊閉包/getter/setter。看看JavaScript中的變量作用域和實現封裝的方法。
作者博客:http://blog.csdn.net/stationxp
作者微博:http://weibo.com/liuhailong2008
轉載請取得作者允許
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/setkeyword控制屬性的讀寫權限。還能夠在執行期通過 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程序猿JavaScript学习笔记(4——关闭/getter/setter)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 发3000元却收回2800元!“慈善主播
- 下一篇: Struts2笔记——15.Spring