2010-04-11 58 views
6

我正在嘗試創建一個UserDon對象,並嘗試以編程方式生成get和set方法(基於John Resig的專業Javascript書第37頁),並且正在Firefox 3.5上測試此方法在javascript中動態創建get/set方法

問題是:在函數UserDon中,「this」是指窗口對象而不是UserDon對象。

所以在調用var userdon = new UserDon(...)後,我在窗口對象(也是setage和getage)上創建了setname和getname方法。

我該如何解決這個問題?

function UserDon(properties) { 
    for(var i in properties) { 
    (function(){ 
     this[ "get" + i ] = function() { 
     return properties[i]; 
     }; 

     this[ "set" + i ] = function(val) { 
     properties[i] = val; 
     }; 
     })(); 
    } 
} 

var userdon = new UserDon({ 
    name: "Bob", 
    age: 44 
}); 
+1

好問題。否則,如果你沒有在getter/setter中做任何額外的操作,你最好只使用公共屬性並放棄方法開銷。 :) – deceze 2010-04-11 04:52:31

回答

7

您正在使用的this值屬於你必須在循環中自動調用函數表達式,當你以這種方式調用的函數,this總是指的是全局對象。

編輯:我錯過了一個事實,即函數表達式是試圖使變量捕捉處理循環內的getter/setter創建,但循環變量i,需要在爲了一個參數傳遞要做到這一點,因爲函數表達式是存在的,上下文(外this)應該被保留:

function UserDon(properties) { 
    var instance = this; // <-- store reference to instance 

    for(var i in properties) { 
    (function (i) { // <-- capture looping variable 
     instance[ "get" + i ] = function() { 
     return properties[i]; 
     }; 

     instance[ "set" + i ] = function(val) { 
     properties[i] = val; 
     }; 
    })(i); // <-- pass the variable 
    } 
} 

var userdon = new UserDon({ 
    name: "Bob", 
    age: 44 
}); 

userdon.getname(); // "Bob" 
userdon.getage(); // 44 

您還可以使用call方法來調用函數表達式,保存上下文(的this值)並介紹CING的循環變量到新的範圍在一個單一的步驟:

function UserDon(properties) { 
    for(var i in properties) { 
    (function (i) { // <-- looping variable introduced 
     this[ "get" + i ] = function() { 
     return properties[i]; 
     }; 

     this[ "set" + i ] = function(val) { 
     properties[i] = val; 
     }; 
    }).call(this, i); // <-- preserve context and capture variable 
    } 
} 

我還建議使用一個if (properties.hasOwnProperty(i)) { ... }for...in循環內,以避免在從Object.prototype繼承用戶擴展屬性迭代。

+1

如果沒有自動調用函數,getname()和getage()將返回44,因爲閉包引用數組的最後一個值,即age,請參閱本書的第29頁。 – portoalet 2010-04-11 08:04:40

+0

@portoalet:你是對的我錯過了這一點,但這還不夠,'i'變量應該作爲參數傳遞給該函數,並且'this'值應該保留,請參閱我的編輯。 – CMS 2010-04-11 08:25:26

+0

謝謝,它現在完美。 – portoalet 2010-04-11 08:41:06

0

使用2個參數獲取泛型函數可能是一個更好的主意:屬性名稱和值(或者只是getter的名稱)。 這個函數會檢查這個屬性是否存在一個特殊函數,如果沒有,就會改變這個屬性的值(或者返回它的getter值)。

0

這裏是我會怎樣代碼時: -

function UserDon(properties) { 
    var self = this; 
    for(var i in properties) { 
    (function(prop){ 
     self[ "get" + prop ] = function() { 
     return properties[prop]; 
     }; 

     self[ "set" + prop ] = function(val) { 
     properties[prop] = val; 
     }; 
     })(i); 
    } 
} 
1

您還可以使用鮮爲人知的
__defineGetter__("varName", function(){});
__defineSetter__("varName", function(val){});

雖然他們是非標準[如X-HTML替換內容類型]他們是由大多數非ie瀏覽器支持[chrome,firefox]

語法應該是:

benjamin = new object(); 
benjamin.__defineGetter__("age", function(){ 
    return 21; 
}); 

或者,你可以,如果這是一個鍛鍊與原型接近這個

benjamin = { 
    get age() 
    { 
    return 21; 
    } 
} 
+0

以前從未見過這個。你自己在用這個嗎? – portoalet 2010-04-12 11:57:20

+1

我只用它來調試變量被獲取/設置的地方。你定義了Setter(「variableName」,outputStackTrace);它也適用於CSS樣式。例如,你說'object.style .__ defineGetter __(「left」,outputStackTraceFunction);'出於某種原因,人們不知道這個函數。可能是因爲它的非標準? – Warty 2010-04-12 20:26:51