2014-01-22 38 views
0

(例如是一本書,但我似乎並沒有得到它)​​特權方法 - 如何獲取傳遞給函數的屬性值?

function User (properties){ 
     for(var i in properties){ 
      (function(){ 
       this["get"+i] = function() { return properties[i];}; 
       this["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
      })(); 
     }// END for 
    }// END User 

var userOne = new User ({ name: "Billy", age: 35 }); 
userOne.getname(); 

當我運行此,用戶沒有getname方法。我如何使特權方法有效?

+0

也許他們在後面解釋什麼是錯誤的,以及需要改變什麼。 – rid

回答

1

這是因爲您使用的立即調用函數

for(var i in properties){ 
     (function(){ //<--- This 
      this["get"+i] = function() { return properties[i];}; 
      this["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
     })(); 
    } 

刪除它,它仍然無法正常工作,但你的方法將在那裏。爲了得到它完全工作,你應該保留i

for(var i in properties){ 
     (function(i){ //<--- This 
      this["get"+i] = function() { return properties[i];}; 
      this["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
     }) (i); //<--- and this 
    } 

後一個問題沒那麼感興趣(雖然相關)的第一個。

JavaScript只有所謂的「功能範圍」,這意味着限制功能範圍的唯一事情是...好...功能。因此,常見的模式是在循環內部或在許多不希望變量泄漏的地方使用IIFE。

但是,javascript中的this參數很奇怪。瞭解以下內容,它將爲您節省一大筆麻煩:this javascript中與其他任何參數沒有區別。

讓我解釋一下。

有四種方法可以在javascript中調用函數。

myFn.call("this param", "param 1", "param 2"); //this is "this param" 
myFn.apply("this param", ["param 1", "param 2"]); //this is "this param" 
myFn("param 1", "param 2"); 
//javascript takes a guess at what `this` should be - 
//usually it is set to the global `window`. 
new myFn("param 1", "param 2"); 
//`this` is a new function with its' prototype set to myFn.prototype 

如果你總是使用.call形式的所有不確定性就會消失,你可以看到,this正是像其他參數。然而,這是額外的語法,人們更喜歡使用更簡單的形式,這意味着你必須考慮什麼是「這個」的規則。

因此,在您的示例中,您正在對全局window對象放置getter和setter。

我要做一個聲明在這裏,你的書可能不會,但我已經從多年的學習撈起,用工作和教學的JavaScript同意:

不要使用newthis關鍵字。

這兩個關鍵字將大量的概念引入到JS中,這些概念令人困惑,而且確實如此 - 除非你讓性能非常敏感(你不是,我知道你認爲你是,但你不是) - 不必要。相反,創建新的對象僅僅是這樣的:

var user = { name: "Billy", age: 35 }; 

如果你絕對必須 getter和setter方法,這將做到這一點:

function createObjectWithProps (properties){ 
    var obj = {}; 
    var state = {}[ 
    for(var k in properties){ 
     (function(key) { 
      obj["get"+key] = function() { return state[key];}; 
      obj["set"+key] = function (valueOne) { state[key] = valueOne; }; 
     })(k) 
    } 
    return obj; 
} 

var userOne = createObjectWithProps ({ name: "Billy", age: 35 }); 
userOne.getname(); 

雖然我會更進一步地指出,getter和setter在js中並不是非常有用,當你使用它們時,遵循類似於knockout的模式是標準的。

+2

這不會把函數裏面的'i'綁定到最後一個'i'嗎? – rid

+0

@rid它不會因爲當你調用它''我'是「當前」值,然後它迭代。 –

+1

您可以測試以查看結果。 'setname'將存在,但它會返回'35'。 – rid

-1

問題是「this」關鍵字。

因爲您在立即調用的函數中使用它,所以它指向全局範圍。

試試這個:

function User (properties){ 

    for(var i in properties){ 
     (function(self,i){ 
      self["get"+i] = function() { return properties[i];}; 
      self["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
     }) (this,i); 
    }// END for 
}// END User 
+0

謝謝擺脫,改變了 –

+0

錯過了!謝謝 –

+0

應該指出,你也可以'.call(this,i)'而不是'(this,i)'並且保留'this [「get」+ ....'東西。儘管如此,我更喜歡它的寫法。 –

3

同時需要thisi在封閉拍攝:

function User (properties){ 
    for(var i in properties){ 
     (function(t, i){ 
      t["get"+i] = function() { return properties[i];}; 
      t["set"+i] = function (valueOne) { properties[i] = valueOne; }; 
     }) (this, i); 
    }// END for 
}// END User 
2

this是不是你認爲誰是。由於您在任何情況下調用了IIFE,所以this將成爲全局範圍,因此該窗口將獲得方法getname等,這不是您所期望的。

要解決它,如果你想保持IIFE,你需要調用它的正確的上下文:

function User (properties){ 
     for(var i in properties){ 
      (function(key){ 
       this["get"+key] = function() { return properties[key];}; 
       this["set"+key] = function (valueOne) { properties[key] = valueOne; }; 
      }).call(this, i); 
     }// END for 
    }// END User 

var userOne = new User ({ name: "Billy", age: 35 }); 
userOne.getname(); 

請注意,您也忘到i參數傳遞給函數,並把它解釋作爲參數。否則所有的功能將被綁定到相同的密鑰,因此userOne.getname將返回35.

相關問題